Bitrix24 How to write custom event handler - bitrix

I want to know where I have to put below custom event handler code in bitrix24(self-hosted system) without changing any core file.
AddEventHandler('socialnetwork', 'OnBeforeSocNetGroupAdd', 'TestHandler');
function TestHandler(&$arFields) {
$arFields['DESCRIPTION'] .= ' It is forbidden to use foul language!';
if ($GLOBALS['USER']->GetID() == 2) {
$GLOBALS['APPLICATION']->throwException('You cannot create groups.');
return false;
}
}

If not custom module, you can put your code in two places:
/bitrix/php_interface/init.php (if there is no init.php file, create it)
or
If you have local folder in the root of the project, you can create file init.php in /local/php_interface/init.php

Related

Discard and re-import dynamic import [duplicate]

From the node.js documentation:
Modules are cached after the first time they are loaded. This means (among other things) that every call to require('foo') will get exactly the same object returned, if it would resolve to the same file.
Is there a way to invalidate this cache? i.e. for unit testing, I'd like each test to be working on a fresh object.
You can always safely delete an entry in require.cache without a problem, even when there are circular dependencies. Because when you delete, you just delete a reference to the cached module object, not the module object itself, the module object will not be GCed because in case of circular dependencies, there is still a object referencing this module object.
Suppose you have:
script a.js:
var b=require('./b.js').b;
exports.a='a from a.js';
exports.b=b;
and script b.js:
var a=require('./a.js').a;
exports.b='b from b.js';
exports.a=a;
when you do:
var a=require('./a.js')
var b=require('./b.js')
you will get:
> a
{ a: 'a from a.js', b: 'b from b.js' }
> b
{ b: 'b from b.js', a: undefined }
now if you edit your b.js:
var a=require('./a.js').a;
exports.b='b from b.js. changed value';
exports.a=a;
and do:
delete require.cache[require.resolve('./b.js')]
b=require('./b.js')
you will get:
> a
{ a: 'a from a.js', b: 'b from b.js' }
> b
{ b: 'b from b.js. changed value',
a: 'a from a.js' }
===
The above is valid if directly running node.js. However, if using tools that have their own module caching system, such as jest, the correct statement would be:
jest.resetModules();
If you always want to reload your module, you could add this function:
function requireUncached(module) {
delete require.cache[require.resolve(module)];
return require(module);
}
and then use requireUncached('./myModule') instead of require.
Yes, you can access the cache via require.cache[moduleName] where moduleName is the name of the module you wish to access. Deleting an entry by calling delete require.cache[moduleName] will cause require to load the actual file.
This is how you would remove all cached files associated with the module:
/**
* Removes a module from the cache
*/
function purgeCache(moduleName) {
// Traverse the cache looking for the files
// loaded by the specified module name
searchCache(moduleName, function (mod) {
delete require.cache[mod.id];
});
// Remove cached paths to the module.
// Thanks to #bentael for pointing this out.
Object.keys(module.constructor._pathCache).forEach(function(cacheKey) {
if (cacheKey.indexOf(moduleName)>0) {
delete module.constructor._pathCache[cacheKey];
}
});
};
/**
* Traverses the cache to search for all the cached
* files of the specified module name
*/
function searchCache(moduleName, callback) {
// Resolve the module identified by the specified name
var mod = require.resolve(moduleName);
// Check if the module has been resolved and found within
// the cache
if (mod && ((mod = require.cache[mod]) !== undefined)) {
// Recursively go over the results
(function traverse(mod) {
// Go over each of the module's children and
// traverse them
mod.children.forEach(function (child) {
traverse(child);
});
// Call the specified callback providing the
// found cached module
callback(mod);
}(mod));
}
};
Usage would be:
// Load the package
var mypackage = require('./mypackage');
// Purge the package from cache
purgeCache('./mypackage');
Since this code uses the same resolver require does, just specify whatever you would for require.
"Unix was not designed to stop its users from doing stupid things, as
that would also stop them from doing clever things." – Doug Gwyn
I think that there should have been a way for performing an explicit uncached module loading.
There's a Simple Module for that (with tests)
We had this exact issue while testing our code (delete cached modules so they can be re-required in a fresh state) so we reviewed all the suggestions of people on the various StackOverflow Questions & Answers and put together a simple node.js module (with tests):
https://www.npmjs.com/package/decache
As you would expect, works for both published npm packages and locally defined modules. Windows, Mac, Linux, etc.
How? (usage)
Usage is pretty simple:
install
Install the module from npm:
npm install decache --save-dev
Use it in your code:
// require the decache module:
const decache = require('decache');
// require a module that you wrote"
let mymod = require('./mymodule.js');
// use your module the way you need to:
console.log(mymod.count()); // 0 (the initial state for our counter is zero)
console.log(mymod.incrementRunCount()); // 1
// delete the cached module:
decache('./mymodule.js');
//
mymod = require('./mymodule.js'); // fresh start
console.log(mymod.count()); // 0 (back to initial state ... zero)
If you have any questions or need more examples, please create a GitHub issue:
https://github.com/dwyl/decache/issues
For anyone coming across this who is using Jest, because Jest does its own module caching, there's a built-in function for this - just make sure jest.resetModules runs eg. after each of your tests:
afterEach( function() {
jest.resetModules();
});
Found this after trying to use decache like another answer suggested. Thanks to Anthony Garvan.
Function documentation here.
The solutions is to use:
delete require.cache[require.resolve(<path of your script>)]
Find here some basic explanations for those who, like me, are a bit new in this:
Suppose you have a dummy example.js file in the root of your directory:
exports.message = "hi";
exports.say = function () {
console.log(message);
}
Then you require() like this:
$ node
> require('./example.js')
{ message: 'hi', say: [Function] }
If you then add a line like this to example.js:
exports.message = "hi";
exports.say = function () {
console.log(message);
}
exports.farewell = "bye!"; // this line is added later on
And continue in the console, the module is not updated:
> require('./example.js')
{ message: 'hi', say: [Function] }
That's when you can use delete require.cache[require.resolve()] indicated in luff's answer:
> delete require.cache[require.resolve('./example.js')]
true
> require('./example.js')
{ message: 'hi', say: [Function], farewell: 'bye!' }
So the cache is cleaned and the require() captures the content of the file again, loading all the current values.
rewire is great for this use case, you get a new instance with each call. Easy dependency injection for node.js unit testing.
rewire adds a special setter and getter to modules so you can modify their behaviour for better unit testing. You may
inject mocks for other modules or globals like process
leak private variables
override variables within the module.
rewire does not load the file and eval the contents to emulate node's require mechanism. In fact it uses node's own require to load the module. Thus your module behaves exactly the same in your test environment as under regular circumstances (except your modifications).
Good news to all caffeine-addicts: rewire works also with Coffee-Script. Note that in this case CoffeeScript needs to be listed in your devDependencies.
I'd add to luff's answer one more line and change the parameter name:
function requireCached(_module){
var l = module.children.length;
for (var i = 0; i < l; i++)
{
if (module.children[i].id === require.resolve(_module))
{
module.children.splice(i, 1);
break;
}
}
delete require.cache[require.resolve(_module)];
return require(_module)
}
Yes, you can invalidate cache.
The cache is stored in an object called require.cache which you can access directly according to filenames (e.g. - /projects/app/home/index.js as opposed to ./home which you would use in a require('./home') statement).
delete require.cache['/projects/app/home/index.js'];
Our team has found the following module useful. To invalidate certain groups of modules.
https://www.npmjs.com/package/node-resource
I am not 100% certain of what you mean by 'invalidate', but you can add the following above the require statements to clear the cache:
Object.keys(require.cache).forEach(function(key) { delete require.cache[key] })
Taken from #Dancrumb's comment here
requireUncached with relative path: 🔥
const requireUncached = require => module => {
delete require.cache[require.resolve(module)];
return require(module);
};
module.exports = requireUncached;
invoke requireUncached with relative path:
const requireUncached = require('../helpers/require_uncached')(require);
const myModule = requireUncached('./myModule');
I couldn't neatly add code in an answer's comment. But I would use #Ben Barkay's answer then add this to the require.uncache function.
// see https://github.com/joyent/node/issues/8266
// use in it in #Ben Barkay's require.uncache function or along with it. whatever
Object.keys(module.constructor._pathCache).forEach(function(cacheKey) {
if ( cacheKey.indexOf(moduleName) > -1 ) {
delete module.constructor._pathCache[ cacheKey ];
}
});
Say you've required a module, then uninstalled it, then reinstalled the same module but used a different version that has a different main script in its package.json, the next require will fail because that main script does not exists because it's cached in Module._pathCache
If you want a module to simply never be cached (sometimes useful for development, but remember to remove it when done!) you can just put delete require.cache[module.id]; inside the module.
here's my version of this answer, which handles not loading a file if it has (for example) syntax errors
function reacquire(module) {
const fullpath = require.resolve(module);
const backup = require.cache[fullpath];
delete require.cache[fullpath];
try {
const newcopy = require(module);
console.log("reqcquired:",module,typeof newcopy);
return newcopy;
} catch (e) {
console.log("Can't reqcquire",module,":",e.message);
require.cache[fullpath] = backup;
return backup;
}
}
Following two step procedure is working perfectly for me.
After changing Model file i-e 'mymodule.js' dynamically, you need to Delete precompiled model in mongoose model first then reload it using require-reload
Example:
// Delete mongoose model
delete mongoose.connection.models[thisObject.singular('mymodule')]
// Reload model
var reload = require('require-reload')(require);
var entityModel = reload('./mymodule.js');
The documentation says:
Modules are cached in this object when they are required. By deleting a key value from this object, the next require will reload the module. This does not apply to native addons, for which reloading will result in an error.
If it's for unit tests, another good tool to use is proxyquire. Everytime you proxyquire the module, it will invalidate the module cache and cache a new one. It also allows you to modify the modules required by the file that you are testing.
I made a small module to delete module from the cache after loading. This forces reevaluation of the module next time it is required. See https://github.com/bahmutov/require-and-forget
// random.js
module.exports = Math.random()
const forget = require('require-and-forget')
const r1 = forget('./random')
const r2 = forget('./random')
// r1 and r2 will be different
// "random.js" will not be stored in the require.cache
PS: you can also put "self-destruct" into the module itself. See https://github.com/bahmutov/unload-me
PSS: more tricks with Node require in my https://glebbahmutov.com/blog/hacking-node-require/

Include functions of different files in Node.js

Okay, so... I load several files from a folder and want the functions from the loaded files to be loaded into the file that loads the files. As if they had been in the file from the start.
My current code works fine so far, but I can't use "this" in the loaded function, because it's not the "this" from the file that loaded the function.
Loading all files and include their functions.
return fs.readdirAsync(path.join(__dirname, 'Handlers')).map(file => {
if (file.substr(file.length - 3) === '.js') {
let handlerFile = require(path.join(__dirname, 'Handlers', file))
for (const handlerName of Object.keys(handlerFile)) {
this[handlerName] = handlerFile[handlerName]
}
}
})
This is how the loaded file looks like:
module.exports = {
test: (arguments) => {
console.log(this)
}
}
So, if I call this.test() now in the file that loaded the function, console.log(this) is executed. Everything works so far, but "this" is empty.
Is there a way that the loaded function gets the "this" from the file that loads the functions? (Without passing it to the function)
I hope you understand what I want. Thanks for any help.
The value of this is not automatically passed from your original environment to the loaded module. When a module is loaded with require(), the value of this in that module is set to the value of module.exports and since your test() method is declared using an arrow function, the value of this inside of your .test() method will be the lexical value of this which in the case of the code you show me will be the original value of module.exports (before you reassigned it) since that's what this was when the module was originally loaded.
If you're calling the .test() method with something like this.test(), then a very simple fix is to just stop using an arrow function for your method and use a regular function. Regular functions called as methods as in obj.test() will set the value of this to be obj in the method. If that's what you want, then just stop using an arrow function. In fact, there are very, very, very few cases where you want a method to be declared using an arrow function. Methods should nearly always be normal function definitions. Remember, an arrow function is NOT just a shortcut syntax. It changes the behavior for setting the value of this.
So, you could just change your loaded file to this:
module.exports = {
test: function(args) {
console.log(this)
}
}

change `dest` option on the fly

I have some grunt tasks to compile files and would like to "recycle" them inside different tasks.
I am trying to modify the destination directory without success... My idea is something like:
grunt.registerTask('bower', ['compile:index', 'compile:core'], function(){
this.options({dest: 'dist/*.js'});
});
The compile:index task runs good by itself (i.e. when called alone) and has dest: 'index.js, other tasks have other filenames. I would like to change these inside the bowertask, adding a new directory but keeping the filename defined in the original task.
Is this possible?
You can create a dynamic alias task that configures and then runs tasks like such:
grunt.registerTask('bower', function(target) {
target = target || 'index';
if (target === 'core') {
grunt.config('compile.core.dest', 'dist/core.js');
} else {
grunt.config('compile.index.dest', 'dist/index.js');
// Will call itself after compile:index has ran to configure for compile:core
grunt.task.run(['compile:index', 'bower:core', 'compile:core']);
}
});
Then entering grunt bower or grunt bower:index will dynamically configure/run the compile:index task, then configure/run the compile:core task.

Include class definition file

How can I include a file, which contains classes definitions in my server.js file?
I don't want to use module.exports because I want to use this file in my client javascript code too.
Thank you!
If you want the module's contents to be available outside the scope of the file you have to use module.exports. Making the file also work in a browser just requires you to do some extra if/elses
For instance:
var self = {};
// Browser?
if(instanceof window !== 'undefined')
{
window['my_module_name'] = self;
}
// Otherwise assume Node.js
else
{
module.exports = self;
}
// Put the contents of this module in self
// For instance:
self.some_module_function = function() {
// Do stuff
}
Now if you're in Node.js you can reach the function like this:
my_module = require('my_module_name');
my_module.some_module_function(58);
Or if you're in a browser you can just call it directly since it's global:
my_module.some_module_function(58);
Otherwise I can recommend Stitch.js which allows you to develop JavaScript code using the CommonJS style require and modules, then compile it to also run in the browser with no code changes.
Require.js also allows for this type of functionality.
Here's another SO question about using the same code in node and browsers:
how to a use client js code in nodejs

Using an emscripten compiled C library from node.js

After following instructions on the emscripten wiki I have managed to compile a small C library. This resulted in an a.out.js file.
I was assuming that to use functions from this library (within node.js) something like this would have worked:
var lib = require("./a.out.js");
lib.myFunction('test');
However this fails. Can anyone help or point me to some basic tutorial related to this?
Actually, all the functions are already exported. Generated JavaScript contains following lines:
var ENVIRONMENT_IS_NODE = typeof process === 'object' && typeof require === 'function';
// …
if (ENVIRONMENT_IS_NODE) {
// …
module['exports'] = Module;
}
If you got a function called my_fun in your C code, then you'll have Module._my_fun defined.
There are some problems with this approach, though.
Optimizer may remove or rename some functions, so always specify them passing -s EXPORTED_FUNCTIONS="['_main','_fun_one','_fun_two']". Function signatures in C++ are bit mangled, so it's wise to extern "C" { … } the ones which you want to export.
Furthermore, such a direct approach requires JS to C type conversions. You may want to hide it by adding yet another API layer in file added attached with --pre-js option:
var Module = {
my_fun: function(some_arg) {
javascript to c conversion goes here;
Module._my_fun(converted_arg) // or with Module.ccall
}
}
Module object will be later enhanced by all the Emscripten-generated goodies, so don't worry that it's defined here, not modified.
Finally, you will surely want to consider Embind which is a mechanism for exposing nice JavaScript APIs provided by Emscripten. (Requires disabling newest fastcomp backend.)
The problem here is that your a.out.js file is going to look like this
function myFunction() {
...
}
Not like this
function myFunction() {
...
}
exports.myFunction = myFunction;
You need to write a build script that lists the tokens you want to publically export from each C program and appends exports.<token> = <token>;\n to the end of your file for each token.

Resources