CakePHP3 Plugin cell is missing - cell

My Process
make plugin cell
$ bin/cake bake plugin Abc
$ bin/cake bake cell Abc.New
upper process make 3 files
plugins/Abc/src/View/Cell/NewCell.php
plugins/Abc/src/Template/Cell/Menu/display.php
and test file.
insert layout/default.ctp next code
<?php $cell = $this->cell('Abc.New'); ?>
error
Cell class Abc.New is missing.
Cake\View\Exception\MissingCellException
I can't find solution. please help me!!

Post is a bit old but in case someone else stumbles on this thread...
Cells rely on Namespaces to load and render the correct [cell].ctp file. In other words, even though you have done the required Plugin::loadAll(); in your bootstrap.php file, you still need to modify the composer.json file and add the Plugin. For example, my Plugin is called 'Metronic', notice the extra 2 lines in autoload and autolaod-dev
"autoload": {
"psr-4": {
"App\\": "src",
"Metronic\\": "./plugins/Metronic/src"
}
},
"autoload-dev": {
"psr-4": {
"App\\Test\\": "tests",
"Cake\\Test\\": "./vendor/cakephp/cakephp/tests",
"Metronic\\Test\\": "./plugins/Metronic/tests"
}
},
See CakePHP manual here http://book.cakephp.org/3.0/en/plugins.html#autoloading-plugin-classes.
My suggestions is that you use the Bake command to create Plugins in the future. The manual does not explicitly say this, but this is what happens when you use the Bake command:
It creates the basic directory structure for the Plugin
It inserts a line in bootstrap.php e.g.Plugin::load('Metronic', ['bootstrap' => false, 'routes' => true]);
It inserts 2 lines in the composer.json file (as per my example above)
The only thing you need to then do is tell Composer to refresh its autoloading cache
$ bin\cake bake plugin Metronic
$ php composer.phar dumpautoload
Hope this helps..

Related

GLB/GLTF File Loading with Storybook and Webpack with file-loader

I have a component library I am creating with Storybook that needs access to .glb/.gltf files. Based on research, it seemed like the best thing to do here was to use the file-loader Webpack functionality, and augment the storybook main.js as such:
// .storybook/main.js
module.exports = {
"stories": [
"../src/**/*.stories.mdx",
"../src/**/*.stories.#(js|jsx|ts|tsx)"
],
"addons": [
"#storybook/addon-links",
"#storybook/addon-essentials",
"#storybook/preset-create-react-app"
],
webpackFinal: async (config, { configType }) => {
config.module.rules.push({
test: /\.(glb|gltf)$/,
use: ['file-loader'],
include: path.resolve(__dirname, '../'),
});
return config;
},
};
Then, in my jsx file that references the mesh:
// src/components/MeshLoader.jsx
import MyMeshFile from "./meshes/MyMesh.glb";
import { useGLTF } from "#react-three/drei";
export default function Model(props) {
const group = useRef();
const { nodes, materials } = useGLTF(MyMeshFile);
// Do more stuff with these things
}
When I run compile, everything works, and if I log what MyMeshFile is, I get a path like:
static/media/MyMesh.976a5ad2.glb, as expected.
However, the rest breaks with an error Uncaught Unexpected token e in JSON at position 0, basically on account of the useGLTF function failing at the contents of that file.
It turns out that http://localhost:6006/static/media/MyMesh.976a5ad2.glb is actually a file with the contents of
export default __webpack_public_path__ + "178cb3da7737741d81a5d4f0c2bcc161.glb";
So it seems like there is some redirection happening. If I direct the browser at http://localhost:6006/178cb3da7737741d81a5d4f0c2bcc161.glb, I get the file I want.
My first question, is whether this is the expected behavior here, given the way I have things set up. If so, it seems like I would have to parse the contents of the file path given by Webpack, and use that to get the actual path. That seems to be a bit convoluted, so is there a better way of handling this?
Thanks for the help!
UPDATE:
I have tested with the gltf-webpack-loader loader, by adding the following to the .storybook/main.js file:
...
config.module.rules.push({
test: /\.(gltf)$/, // Removed gltf from file-loader
use: [{loader: "gltf-webpack-loader"}]
})
...
And tried the same thing with a gltf file. I get the same behavior of receiving the "redirect" file instead of the actual one I want.
So it turns out that there is currently a bug with "#storybook/preset-create-react-app" that is causing this issue. Removing that add-on seems to resolve the issue described here, although it does produce a warning that:
Storybook support for Create React App is now a separate preset.
WARN To use the new preset, install `#storybook/preset-create-react-app` and add it to the list of `addons` in your `.storybook/main.js` config file.
WARN The built-in preset has been disabled in Storybook 6.0.

In-repo addon writing public files on build causes endless build loop on serve

I'm having difficulty with my in-repo addon writing to appDir/public. What I'd like to do is write out a JSON file on each build to be included in the app /dist. The problem I'm running into is when running "ember serve", the file watcher detects the new file and rebuilds again, causing an endless loop.
I've tried writing the JSON file using preBuild() and postBuild() hooks, saving to /public, but after build, the watcher detects it and rebuild over and over, writing a new file again each time. I also tried using my-addon/public folder and writing to that, same thing.
The only thing that partially works is writing on init(), which is fine, except I don't see the changes using ember serve.
I did try using the treeForPublic() method, but did not get any further. I can write the file and use treeForPublic(). This only runs once though, on initial build. It partially solves my problem, because I get the files into app dist folder. But I don't think ember serve will re-run treeForPublic on subsequent file change in the app.
Is there a way to ignore specific files from file watch? Yet still allow files to include into the build? Maybe there's an exclude watch property in ember-cli-build?
Here's my treeForPublic() , but I'm guessing my problems aren't here:
treeForPublic: function() {
const publicTree = this._super.treeForPublic.apply(this, arguments);
const trees = [];
if (publicTree) {
trees.push(publicTree);
}
// this writes out the json
this.saveSettingsFile(this.pubSettingsFile, this.settings);
trees.push(new Funnel(this.addonPubDataPath, {
include: [this.pubSettingsFileName],
destDir: '/data'
}));
return mergeTrees(trees);
},
UPDATE 05/20/2019
I should probably make a new question at this point...
My goal here is to create an auto-increment build number that updates both on ember build and ember serve. My comments under #real_ates's answer below help explain why. In the end, if I can only use this on build, that's totally ok.
The answer from #real_ate was very helpful and solved the endless loop problem, but it doesn't run on ember serve. Maybe this just can't be done, but I'd really like to know either way. I'm currently trying to change environment variables instead of using treeforPublic(). I've asked that as a separate question about addon config() updates to Ember environment:
Updating Ember.js environment variables do not take effect using in-repo addon config() method on ember serve
I don't know if can mark #real_ate's answer as the accepted solution because it doesn't work on ember serve. It was extremely helpful and educational!
This is a great question, and it's often something that people can be a bit confused about when working with broccoli (I know for sure that I've been stung by this in the past)
The issue that you have is that your treeForPublic() is actually writing a file to the source directory and then you're using broccoli-funnel to select that new custom file and include it in the build. The correct method to do this is instead to use broccoli-file-creator to create an output tree that includes your new file. I'll go into more detail with an example below:
treeForPublic: function() {
const publicTree = this._super.treeForPublic.apply(this, arguments);
const trees = [];
if (publicTree) {
trees.push(publicTree);
}
let data = getSettingsData(this.settings);
trees.push(writeFile('/data/the-settings-file.json', JSON.stringify(data)));
return mergeTrees(trees);
}
As you will see the most of the code is exactly the same as your example. The two main differences are that instead of having a function this.saveSettingsFile() that writes out a settings file on disk we now have a function this.getSettingsData() that returns the content that we would like to see in the newly created file. Here is the simple example that we came up with when we were testing this out:
function getSettingsData() {
return {
setting1: 'face',
setting2: 'my',
}
}
you can edit this function to take whatever parameters you need it to and have whatever functionality you would like.
The next major difference is that we are using the writeFile() function which is actually just the broccoli-file-creator plugin. Here is the import that you would put at the top of the file:
let writeFile = require('broccoli-file-creator');
Now when you run your application it won't be writing to the source directory any more which means it will stop constantly reloading 🎉
This question was answered as part of "May I Ask a Question" Season 2 Episode 2. If you would like to see us discuss this answer in full you can check out the video here: https://youtu.be/9kMGMK9Ur4E

How to use Polymer 2 Build Process?

I know this might be a duplicate of this question but there was no clear answer ever.
Polymer 2 Framework has a quite good documentation so far but when it comes to the build process there`s not enough explanation.
I've successfully created my own element, also with external scripts referenced and everything runs fine with
polymer serve --open
But I've spent so much time to get this built and to include the output into a minimal HTML template without success. Is it really that tricky?
I`ve even tried again with the empty element template, no chance. This template has a nearly blank polymer.json:
{
"lint": {
"rules": [
"polymer-2"
]
}
}
If I build that right away with
polymer build
(should use default build behaviour) then I get a default build folder with an index.html and bower_components folder. There`s no reference to my created custom element ("Hello ...").
What do I have to do to get a final build of this "Hello Something" template and include it into a minimum html page?
There are a lot of different ways to go from single component to app with that single component, and I'm not going to say 100% that this is the best, but it should work. "What do I have to do to get a final build of this "Hello Something" template and include it into a minimum html page?", is a pretty flexible request, so even in the below there could be lots of alternatives for you, but the following would be my suggestion. We'll start in the command line, from the Desktop or a folder where you keep you projects.
mkdir minimal-html-page
cd minimal-html-page
polymer init
// here make sure you choose `polymer-2-application` other questions re of little consequence in this specific use case
bower install {yourComponent} --save
// in that case that you haven't published to github, copy and paste also works. Paste into the `src` directory if that's the case.
atom .
// or whatever editor you prefer
Now you're in your project, and there is just one change needed to get you going.
index.html
Change the current HTML import
<link rel="import" href="/src/build-test-app/build-test-app.html">
to link to your component.
At this point you should be free to use polymer build to have the project built, then it'll structure your code to be deployed in other applications via something that will look like
<script src="/bower_components/webcomponentsjs/webcomponents-loader.js"></script>
<link rel="import" href="/src/build-test-app/build-test-app.html">
<build-test-app></build-test-app>
This is the most basic of builds and won't account for any x-browser or performance goals you might have in your project. You'll also see in the build/default directory all the files you'd need to copy/paste to use the component elsewhere.
If you do have x-browser expectations, you can solve them fairly easily by using the polymer build --compile command. This will create slightly more complex embed code to manage either side of the ES5/6 capability boundary and will look something like:
<script>!function(e){var r=e.babelHelpers={};r.typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},r.classCallCheck=function(e,r){if(!(e instanceof r))throw new TypeError("Cannot call a class as a function")},r.createClass=function(){function e(e,r){for(var t=0;t<r.length;t++){var n=r[t];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}return function(r,t,n){return t&&e(r.prototype,t),n&&e(r,n),r}}(),r.defineEnumerableProperties=function(e,r){for(var t in r){var n=r[t];n.configurable=n.enumerable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,t,n)}return e},r.defaults=function(e,r){for(var t=Object.getOwnPropertyNames(r),n=0;n<t.length;n++){var o=t[n],i=Object.getOwnPropertyDescriptor(r,o);i&&i.configurable&&void 0===e[o]&&Object.defineProperty(e,o,i)}return e},r.defineProperty=function(e,r,t){return r in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e},r.extends=Object.assign||function(e){for(var r=1;r<arguments.length;r++){var t=arguments[r];for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])}return e},r.get=function e(r,t,n){null===r&&(r=Function.prototype);var o=Object.getOwnPropertyDescriptor(r,t);if(void 0===o){var i=Object.getPrototypeOf(r);return null===i?void 0:e(i,t,n)}if("value"in o)return o.value;var a=o.get;if(void 0!==a)return a.call(n)},r.inherits=function(e,r){if("function"!=typeof r&&null!==r)throw new TypeError("Super expression must either be null or a function, not "+typeof r);e.prototype=Object.create(r&&r.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),r&&(Object.setPrototypeOf?Object.setPrototypeOf(e,r):e.__proto__=r)},r.instanceof=function(e,r){return null!=r&&"undefined"!=typeof Symbol&&r[Symbol.hasInstance]?r[Symbol.hasInstance](e):e instanceof r},r.newArrowCheck=function(e,r){if(e!==r)throw new TypeError("Cannot instantiate an arrow function")},r.objectDestructuringEmpty=function(e){if(null==e)throw new TypeError("Cannot destructure undefined")},r.objectWithoutProperties=function(e,r){var t={};for(var n in e)r.indexOf(n)>=0||Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t},r.possibleConstructorReturn=function(e,r){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!r||"object"!=typeof r&&"function"!=typeof r?e:r},r.set=function e(r,t,n,o){var i=Object.getOwnPropertyDescriptor(r,t);if(void 0===i){var a=Object.getPrototypeOf(r);null!==a&&e(a,t,n,o)}else if("value"in i&&i.writable)i.value=n;else{var u=i.set;void 0!==u&&u.call(o,n)}return n},r.slicedToArray=function(){function e(e,r){var t=[],n=!0,o=!1,i=void 0;try{for(var a,u=e[Symbol.iterator]();!(n=(a=u.next()).done)&&(t.push(a.value),!r||t.length!==r);n=!0);}catch(e){o=!0,i=e}finally{try{!n&&u.return&&u.return()}finally{if(o)throw i}}return t}return function(r,t){if(Array.isArray(r))return r;if(Symbol.iterator in Object(r))return e(r,t);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}(),r.taggedTemplateLiteral=function(e,r){return Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(r)}}))},r.temporalRef=function(e,r,t){if(e===t)throw new ReferenceError(r+" is not defined - temporal dead zone");return e},r.temporalUndefined={},r.toArray=function(e){return Array.isArray(e)?e:Array.from(e)},r.toConsumableArray=function(e){if(Array.isArray(e)){for(var r=0,t=Array(e.length);r<e.length;r++)t[r]=e[r];return t}return Array.from(e)}}("undefined"==typeof global?self:global);</script>
<script>if (!window.customElements) { document.write('<!--'); }</script>
<script type="text/javascript" src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
<!--! do not remove -->
<script src="/bower_components/webcomponentsjs/webcomponents-loader.js"></script>
<link rel="import" href="/src/build-test-app/build-test-app.html">
<build-test-app></build-test-app>
The <!--! do not remove --> part is super not kidding and it integral to making sure the compiled code works in ES6 environments.
Beyond that, there is a whole world of things that you can do to tune this up for production deployment. I'd research https://www.polymer-project.org/2.0/docs/tools/polymer-cli-commands#build and https://www.polymer-project.org/2.0/docs/tools/polymer-json to get a better handle on that.
Re polymer build "This command is for app projects only." (https://www.polymer-project.org/2.0/docs/tools/polymer-cli-commands#build)
Also, shell is required. See https://www.polymer-project.org/2.0/docs/tools/polymer-json#shell.

How does the Opencart system/modifications folder function?

I am quite new to OC 2.X and I noticed as I was making changes to the site they werent appearing. When I went to change within the system/modifications folder the changes appeared. I assumed this folder was something new and nothing to do with vqmod. I thought it was a foler that would basically take priority over the core file.
Unfortunately when I installed a plugin it also rebuilt that folder so Ive lost all my changes (Im assuming thats what happened).
Im wondering how does this work overall? Must I make a new extension for every change I would like to make?
I cannot find a clear and concise explanation that explains it for a developers point of view.
You can say that ocmod is same as vqmod but it differs in some ways and provided by default in opencart 2.0 and above version. You have to reset modification cache every time you make any changes to your module to see its effect. Like vqmod ocmod also generates cache files which are placed in modification folder. And files in this folder will get prior then the original one. As i think you were modifying files in modification file you might lose them if you clear modification cache from admin panel.
You can check system/startup.php file for more understanding.
// Modification Override
function modification($filename) {
if (!defined('DIR_CATALOG')) {
$file = DIR_MODIFICATION . 'catalog/' . substr($filename, strlen(DIR_APPLICATION));
} else {
$file = DIR_MODIFICATION . 'admin/' . substr($filename, strlen(DIR_APPLICATION));
}
if (substr($filename, 0, strlen(DIR_SYSTEM)) == DIR_SYSTEM) {
$file = DIR_MODIFICATION . 'system/' . substr($filename, strlen(DIR_SYSTEM));
}
if (is_file($file)) {
return $file;
}
return $filename;
}

using phpunit without composer

I'm trying to instal PHPunit on an old system,
I'm dealing with several phar issues,
from now i've managed to have PHPunit running, to have my autoload working, also the pPHPunit, but now, it is trying to call composer.
i Had to add an extention "PHPUnit/Extensions/Story", it's also working, but now, i've got to manage composer...
I tried to add the phar, to extract the phar , ... but nothing seems to work (if "Composer\Autoload\ClassLoader.php" work, then I've got an "Instantiator\Instantiator.php" missing...)
So, is it possible to have PHPunit running without composer?
I juste solved the problem :
despite I called "spl_autoload_register" for my own framework afeter including PHPunit and Composer"s ones, mine was sometimes called before, so I juste added a whitelisting in my autoloader (see $tabLibCommunPrefixes):
function phpunit_bootstrap_autoload($class_name) {
$prefixe = substr($class_name, 0, strpos($class_name, '_'));
$tabLibCommunPrefixes = array('Smarty', 'Zend', 'Bvb', 'Composer', 'domxml-php4-compat', 'FirePhp', 'Mobile', 'Nusoap', 'Pear', 'phing', 'PhpMailer', 'phpThumb', 'Sitra', 'Smarty3', 'smarty', 'test', 'upload', );
if (in_array($prefixe, $tabLibCommunPrefixes)) {
require_once str_replace('_', '/', $class_name) . '.php';
return true;
}
return false;
}
One can simply use composer to handle only PHPunit and it's dependencies.
So the easiest way is to simply use composer. There is nothing wrong at using composer for just a small part of your dependencies. In fact, for some (small) projects I even use it for no dependency at all (only to handle the autoloading).
You can use it in the subdirectory test, or more conventionally at the root of the project.