Jump to content


  • Content count

  • Joined

  • Last visited

  • Days Won


Everything posted by iwato

  1. By changing the file's extension from .html to .php and then using the $.get() method to call it in its modified format the problem was resolved. Unfortunately, I am still confused as to why this modification was necessary, when I have other files with the HTML extension that have no trouble processing PHP. Roddy
  2. OK. This makes sense, and a little research has revealed the file that handles the parsed query string. Obviously I could by-pass the need to write a query string by simply supplying the appropriate values for the public functions that generate the desired reports. It would appear that my next challenge would be to make sure that everything that is needed is present when I call the appropriate method. Below is the file in which the appropriate functions are found. Does a quick review of the file suggest that my idea is plausible? INSIDE MATOMO <./matomo/core/FrontController.php> namespace Piwik; use Exception; use Piwik\API\Request; use Piwik\Container\StaticContainer; use Piwik\Exception\AuthenticationFailedException; <?php /** * Piwik - free/libre analytics platform * * @link http://piwik.org * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later * */ namespace Piwik; use Exception; use Piwik\API\Request; use Piwik\Container\StaticContainer; use Piwik\Exception\AuthenticationFailedException; use Piwik\Exception\DatabaseSchemaIsNewerThanCodebaseException; use Piwik\Exception\PluginDeactivatedException; use Piwik\Exception\StylesheetLessCompileException; use Piwik\Http\ControllerResolver; use Piwik\Http\Router; use Piwik\Plugins\CoreAdminHome\CustomLogo; /** * This singleton dispatches requests to the appropriate plugin Controller. * * Piwik uses this class for all requests that go through **index.php**. Plugins can * use it to call controller actions of other plugins. * * ### Examples * * **Forwarding controller requests** * * public function myConfiguredRealtimeMap() * { * $_GET['changeVisitAlpha'] = false; * $_GET['removeOldVisits'] = false; * $_GET['showFooterMessage'] = false; * return FrontController::getInstance()->dispatch('UserCountryMap', 'realtimeMap'); * } * * **Using other plugin controller actions** * * public function myPopupWithRealtimeMap() * { * $_GET['changeVisitAlpha'] = false; * $_GET['removeOldVisits'] = false; * $_GET['showFooterMessage'] = false; * $realtimeMap = FrontController::getInstance()->dispatch('UserCountryMap', 'realtimeMap'); * * $view = new View('@MyPlugin/myPopupWithRealtimeMap.twig'); * $view->realtimeMap = $realtimeMap; * return $realtimeMap->render(); * } * * For a detailed explanation, see the documentation [here](https://developer.piwik.org/guides/how-piwik-works). * * @method static \Piwik\FrontController getInstance() */ class FrontController extends Singleton { const DEFAULT_MODULE = 'CoreHome'; /** * Set to false and the Front Controller will not dispatch the request * * @var bool */ public static $enableDispatch = true; /** * @var bool */ private $initialized = false; /** * @param $lastError * @return string * @throws AuthenticationFailedException * @throws Exception */ private static function generateSafeModeOutputFromError($lastError) { Common::sendResponseCode(500); $controller = FrontController::getInstance(); try { $controller->init(); $message = $controller->dispatch('CorePluginsAdmin', 'safemode', array($lastError)); } catch(Exception $e) { // may fail in safe mode (eg. global.ini.php not found) $message = sprintf("Matomo encoutered an error: %s (which lead to: %s)", $lastError['message'], $e->getMessage()); } return $message; } /** * @param Exception $e * @return string */ private static function generateSafeModeOutputFromException($e) { $error = array( 'message' => $e->getMessage(), 'file' => $e->getFile(), 'line' => $e->getLine() ); return self::generateSafeModeOutputFromError($error); } /** * Executes the requested plugin controller method. * * @throws Exception|\Piwik\Exception\PluginDeactivatedException in case the plugin doesn't exist, the action doesn't exist, * there is not enough permission, etc. * * @param string $module The name of the plugin whose controller to execute, eg, `'UserCountryMap'`. * @param string $action The controller method name, eg, `'realtimeMap'`. * @param array $parameters Array of parameters to pass to the controller method. * @return void|mixed The returned value of the call. This is the output of the controller method. * @api */ public function dispatch($module = null, $action = null, $parameters = null) { if (self::$enableDispatch === false) { return; } $filter = new Router(); $redirection = $filter->filterUrl(Url::getCurrentUrl()); if ($redirection !== null) { Url::redirectToUrl($redirection); return; } try { $result = $this->doDispatch($module, $action, $parameters); return $result; } catch (NoAccessException $exception) { Log::debug($exception); /** * Triggered when a user with insufficient access permissions tries to view some resource. * * This event can be used to customize the error that occurs when a user is denied access * (for example, displaying an error message, redirecting to a page other than login, etc.). * * @param \Piwik\NoAccessException $exception The exception that was caught. */ Piwik::postEvent('User.isNotAuthorized', array($exception), $pending = true); } catch (\Twig_Error_Runtime $e) { echo $this->generateSafeModeOutputFromException($e); exit; } catch(StylesheetLessCompileException $e) { echo $this->generateSafeModeOutputFromException($e); exit; } catch(\Error $e) { echo $this->generateSafeModeOutputFromException($e); exit; } } /** * Executes the requested plugin controller method and returns the data, capturing anything the * method `echo`s. * * _Note: If the plugin controller returns something, the return value is returned instead * of whatever is in the output buffer._ * * @param string $module The name of the plugin whose controller to execute, eg, `'UserCountryMap'`. * @param string $actionName The controller action name, eg, `'realtimeMap'`. * @param array $parameters Array of parameters to pass to the controller action method. * @return string The `echo`'d data or the return value of the controller action. * @deprecated */ public function fetchDispatch($module = null, $actionName = null, $parameters = null) { ob_start(); $output = $this->dispatch($module, $actionName, $parameters); // if nothing returned we try to load something that was printed on the screen if (empty($output)) { $output = ob_get_contents(); } else { // if something was returned, flush output buffer as it is meant to be written to the screen ob_flush(); } ob_end_clean(); return $output; } /** * Called at the end of the page generation */ public function __destruct() { try { if (class_exists('Piwik\\Profiler') && !SettingsServer::isTrackerApiRequest() ) { // in tracker mode Piwik\Tracker\Db\Pdo\Mysql does currently not implement profiling Profiler::displayDbProfileReport(); Profiler::printQueryCount(); } } catch (Exception $e) { Log::debug($e); } } // Should we show exceptions messages directly rather than display an html error page? public static function shouldRethrowException() { // If we are in no dispatch mode, eg. a script reusing Piwik libs, // then we should return the exception directly, rather than trigger the event "bad config file" // which load the HTML page of the installer with the error. return (defined('PIWIK_ENABLE_DISPATCH') && !PIWIK_ENABLE_DISPATCH) || Common::isPhpCliMode() || SettingsServer::isArchivePhpTriggered(); } public static function setUpSafeMode() { register_shutdown_function(array('\\Piwik\\FrontController', 'triggerSafeModeWhenError')); } public static function triggerSafeModeWhenError() { $lastError = error_get_last(); if (!empty($lastError) && $lastError['type'] == E_ERROR) { $message = self::generateSafeModeOutputFromError($lastError); echo $message; } } /** * Must be called before dispatch() * - checks that directories are writable, * - loads the configuration file, * - loads the plugin, * - inits the DB connection, * - etc. * * @throws Exception * @return void */ public function init() { if ($this->initialized) { return; } $this->initialized = true; $tmpPath = StaticContainer::get('path.tmp'); $directoriesToCheck = array( $tmpPath, $tmpPath . '/assets/', $tmpPath . '/cache/', $tmpPath . '/logs/', $tmpPath . '/tcpdf/', $tmpPath . '/templates_c/', ); Filechecks::dieIfDirectoriesNotWritable($directoriesToCheck); $this->handleMaintenanceMode(); $this->handleProfiler(); $this->handleSSLRedirection(); Plugin\Manager::getInstance()->loadPluginTranslations(); Plugin\Manager::getInstance()->loadActivatedPlugins(); // try to connect to the database try { Db::createDatabaseObject(); Db::fetchAll("SELECT DATABASE()"); } catch (Exception $exception) { if (self::shouldRethrowException()) { throw $exception; } Log::debug($exception); /** * Triggered when Piwik cannot connect to the database. * * This event can be used to start the installation process or to display a custom error * message. * * @param Exception $exception The exception thrown from creating and testing the database * connection. */ Piwik::postEvent('Db.cannotConnectToDb', array($exception), $pending = true); throw $exception; } // try to get an option (to check if data can be queried) try { Option::get('TestingIfDatabaseConnectionWorked'); } catch (Exception $exception) { if (self::shouldRethrowException()) { throw $exception; } Log::debug($exception); /** * Triggered when Piwik cannot access database data. * * This event can be used to start the installation process or to display a custom error * message. * * @param Exception $exception The exception thrown from trying to get an option value. */ Piwik::postEvent('Config.badConfigurationFile', array($exception), $pending = true); throw $exception; } // Init the Access object, so that eg. core/Updates/* can enforce Super User and use some APIs Access::getInstance(); /** * Triggered just after the platform is initialized and plugins are loaded. * * This event can be used to do early initialization. * * _Note: At this point the user is not authenticated yet._ */ Piwik::postEvent('Request.dispatchCoreAndPluginUpdatesScreen'); $this->throwIfPiwikVersionIsOlderThanDBSchema(); $module = Piwik::getModule(); $action = Piwik::getAction(); if (empty($module) || empty($action) || $module !== 'Installation' || !in_array($action, array('getInstallationCss', 'getInstallationJs'))) { \Piwik\Plugin\Manager::getInstance()->installLoadedPlugins(); } // ensure the current Piwik URL is known for later use if (method_exists('Piwik\SettingsPiwik', 'getPiwikUrl')) { SettingsPiwik::getPiwikUrl(); } /** * Triggered before the user is authenticated, when the global authentication object * should be created. * * Plugins that provide their own authentication implementation should use this event * to set the global authentication object (which must derive from {@link Piwik\Auth}). * * **Example** * * Piwik::addAction('Request.initAuthenticationObject', function() { * StaticContainer::getContainer()->set('Piwik\Auth', new MyAuthImplementation()); * }); */ Piwik::postEvent('Request.initAuthenticationObject'); try { $authAdapter = StaticContainer::get('Piwik\Auth'); } catch (Exception $e) { $message = "Authentication object cannot be found in the container. Maybe the Login plugin is not activated? <br />You can activate the plugin by adding:<br /> <code>Plugins[] = Login</code><br /> under the <code>[Plugins]</code> section in your config/config.ini.php"; $ex = new AuthenticationFailedException($message); $ex->setIsHtmlMessage(); throw $ex; } Access::getInstance()->reloadAccess($authAdapter); // Force the auth to use the token_auth if specified, so that embed dashboard // and all other non widgetized controller methods works fine if (Common::getRequestVar('token_auth', false, 'string') !== false) { Request::reloadAuthUsingTokenAuth(); } SettingsServer::raiseMemoryLimitIfNecessary(); \Piwik\Plugin\Manager::getInstance()->postLoadPlugins(); /** * Triggered after the platform is initialized and after the user has been authenticated, but * before the platform has handled the request. * * Piwik uses this event to check for updates to Piwik. */ Piwik::postEvent('Platform.initialized'); } protected function prepareDispatch($module, $action, $parameters) { if (is_null($module)) { $module = Common::getRequestVar('module', self::DEFAULT_MODULE, 'string'); } if (is_null($action)) { $action = Common::getRequestVar('action', false); } if (SettingsPiwik::isPiwikInstalled() && ($module !== 'API' || ($action && $action !== 'index')) ) { Session::start(); $this->closeSessionEarlyForFasterUI(); } if (is_null($parameters)) { $parameters = array(); } if (!ctype_alnum($module)) { throw new Exception("Invalid module name '$module'"); } list($module, $action) = Request::getRenamedModuleAndAction($module, $action); if (!\Piwik\Plugin\Manager::getInstance()->isPluginActivated($module)) { throw new PluginDeactivatedException($module); } return array($module, $action, $parameters); } protected function handleMaintenanceMode() { if ((Config::getInstance()->General['maintenance_mode'] != 1) || Common::isPhpCliMode()) { return; } Common::sendResponseCode(503); $logoUrl = 'plugins/Morpheus/images/logo.svg'; $faviconUrl = 'plugins/CoreHome/images/favicon.png'; try { $logo = new CustomLogo(); if ($logo->hasSVGLogo()) { $logoUrl = $logo->getSVGLogoUrl(); } else { $logoUrl = $logo->getHeaderLogoUrl(); } $faviconUrl = $logo->getPathUserFavicon(); } catch (Exception $ex) { } $recordStatistics = Config::getInstance()->Tracker['record_statistics']; $trackMessage = ''; if ($recordStatistics) { $trackMessage = 'Your analytics data will continue to be tracked as normal.'; } else { $trackMessage = 'While the maintenance mode is active, data tracking is disabled.'; } $page = file_get_contents(PIWIK_INCLUDE_PATH . '/plugins/Morpheus/templates/maintenance.tpl'); $page = str_replace('%logoUrl%', $logoUrl, $page); $page = str_replace('%faviconUrl%', $faviconUrl, $page); $page = str_replace('%piwikTitle%', Piwik::getRandomTitle(), $page); $page = str_replace('%trackMessage%', $trackMessage, $page); echo $page; exit; } protected function handleSSLRedirection() { // Specifically disable for the opt out iframe if (Piwik::getModule() == 'CoreAdminHome' && Piwik::getAction() == 'optOut') { return; } // Disable Https for VisitorGenerator if (Piwik::getModule() == 'VisitorGenerator') { return; } if (Common::isPhpCliMode()) { return; } // proceed only when force_ssl = 1 if (!SettingsPiwik::isHttpsForced()) { return; } Url::redirectToHttps(); } private function closeSessionEarlyForFasterUI() { $isDashboardReferrer = !empty($_SERVER['HTTP_REFERER']) && strpos($_SERVER['HTTP_REFERER'], 'module=CoreHome&action=index') !== false; $isAllWebsitesReferrer = !empty($_SERVER['HTTP_REFERER']) && strpos($_SERVER['HTTP_REFERER'], 'module=MultiSites&action=index') !== false; if ($isDashboardReferrer && !empty($_POST['token_auth']) && Common::getRequestVar('widget', 0, 'int') === 1 ) { Session::close(); } if (($isDashboardReferrer || $isAllWebsitesReferrer) && Common::getRequestVar('viewDataTable', '', 'string') === 'sparkline' ) { Session::close(); } } private function handleProfiler() { if (!empty($_GET['xhprof'])) { $mainRun = $_GET['xhprof'] == 1; // core:archive command sets xhprof=2 Profiler::setupProfilerXHProf($mainRun); } } /** * @param $module * @param $action * @param $parameters * @return mixed */ private function doDispatch($module, $action, $parameters) { list($module, $action, $parameters) = $this->prepareDispatch($module, $action, $parameters); /** * Triggered directly before controller actions are dispatched. * * This event can be used to modify the parameters passed to one or more controller actions * and can be used to change the controller action being dispatched to. * * @param string &$module The name of the plugin being dispatched to. * @param string &$action The name of the controller method being dispatched to. * @param array &$parameters The arguments passed to the controller action. */ Piwik::postEvent('Request.dispatch', array(&$module, &$action, &$parameters)); /** @var ControllerResolver $controllerResolver */ $controllerResolver = StaticContainer::get('Piwik\Http\ControllerResolver'); $controller = $controllerResolver->getController($module, $action, $parameters); /** * Triggered directly before controller actions are dispatched. * * This event exists for convenience and is triggered directly after the {@hook Request.dispatch} * event is triggered. * * It can be used to do the same things as the {@hook Request.dispatch} event, but for one controller * action only. Using this event will result in a little less code than {@hook Request.dispatch}. * * @param array &$parameters The arguments passed to the controller action. */ Piwik::postEvent(sprintf('Controller.%s.%s', $module, $action), array(&$parameters)); $result = call_user_func_array($controller, $parameters); /** * Triggered after a controller action is successfully called. * * This event exists for convenience and is triggered immediately before the {@hook Request.dispatch.end} * event is triggered. * * It can be used to do the same things as the {@hook Request.dispatch.end} event, but for one * controller action only. Using this event will result in a little less code than * {@hook Request.dispatch.end}. * * @param mixed &$result The result of the controller action. * @param array $parameters The arguments passed to the controller action. */ Piwik::postEvent(sprintf('Controller.%s.%s.end', $module, $action), array(&$result, $parameters)); /** * Triggered after a controller action is successfully called. * * This event can be used to modify controller action output (if any) before the output is returned. * * @param mixed &$result The controller action result. * @param array $parameters The arguments passed to the controller action. */ Piwik::postEvent('Request.dispatch.end', array(&$result, $module, $action, $parameters)); return $result; } /** * This method ensures that Piwik Platform cannot be running when using a NEWER database. */ private function throwIfPiwikVersionIsOlderThanDBSchema() { // When developing this situation happens often when switching branches if (Development::isEnabled()) { return; } $updater = new Updater(); $dbSchemaVersion = $updater->getCurrentComponentVersion('core'); $current = Version::VERSION; if (-1 === version_compare($current, $dbSchemaVersion)) { $messages = array( Piwik::translate('General_ExceptionDatabaseVersionNewerThanCodebase', array($current, $dbSchemaVersion)), Piwik::translate('General_ExceptionDatabaseVersionNewerThanCodebaseWait'), // we cannot fill in the Super User emails as we are failing before Authentication was ready Piwik::translate('General_ExceptionContactSupportGeneric', array('', '')) ); throw new DatabaseSchemaIsNewerThanCodebaseException(implode(" ", $messages)); } } } Roddy
  3. Though I did not see any 404 errors I certainly saw links that appeared to be failing in their destination. So, what is it about a src attribute that insures that everything is loaded into the widget before it is displayed in the iframe? I will be far less eager to take advantage of Matomo's widgets, if I have to reconfigure each and every broken link for each and every widget that I decide to incorporate into my webpage. Roddy
  4. Recently my hostserver modified their system and notified me of an .htaccess file that they placed on my website so that my HTML files could handle PHP. I opened and examined it, but saw nothing out of the ordinary. In fact, it appears very similar to what I use to use on my own test server before my hard disk failure. The file's permissions are 644. Might the problem be related to the absence of header tags? Once again, the file is little more than a text file with an .html extension. The document begins and ends with the same <div> element. Roddy
  5. No, you have the wrong idea about Matomo. I have nicknamed it Google Analytics without Google, for unlike Google everything is yours: the data that you collect as well as the application itself reside on your own server. Now, Matomo does offer a cloud, but you are by no means obligated to use it. Further, Matomo is a very portable self-contained package. Even, it has its own vendor folder for dependencies. Once you have downloaded and installed the package, you are free to do with it what you please within the normal restrictions of open-source software. Yes, there is an API. In fact, in the manual the word API is used everywhere to the point where it no longer makes any sense. In any case, I have been told that all reporting requests must pass through a file called index.php. With this understanding I composed a .php file with the following contents and ran the same query string that I successfully ran using an HTTP request from another file on my website.. The variable dump produces boolean false. ini_set('log_errors', 1); ini_set('error_log', dirname(__FILE__) . DIRECTORY_SEPARATOR . 'error.log'); ini_set('html_errors', 0); ini_set('display_errors', 0); error_reporting(E_ALL); define('PIWIK_INCLUDE_PATH', realpath('../../../../the_path_to_the_matomo_folder/matomo')); $result = file_get_contents(PIWIK_INCLUDE_PATH . DIRECTORY_SEPARATOR . 'index.php?module=API&action=index&method=VisitsSummary.get&idSite=1&period=year&date=today&format=json&token_auth=&token_auth=my_authorization_token'); var_dump($result); When I examine the error.log file I am told [02-Jun-2018 01:32:25 UTC] PHP Warning: file_get_contents(/home/.../public_html/path_to_matomo_folder/php/matomo/index.php?module=API&action=index&method=VisitsSummary.get&idSite=1&period=year&date=today&format=json&token_auth=&token_auth=my_authorization_token): failed to open stream: No such file or directory in /home/.../public_html/path_to the _folder_containing_the_requesting_file/direct_request.php on line 9 Line 9 is file_get_contents() method containing the path to the index.php file. Roddy
  6. Although more complex than what I am writing here, one may think of Matomo, at least for our purposes, as divided into two parts: tracking and reporting. Although one may track with PHP, I am using Javascript for this purpose. On the reporting side Matomo offered either of two means: indirect HTTP requests with a GET query string, or direct access via a large variety of get methods categorize by the PHP classes that defined them. As Matomo is known on the internet for being resource intensive, and as I am working on shared SSL server, I prefer the latter means of accessing the report methods. In this spirit I brought it to the attention of Matomo that their recommended code did not perform as suggested, and they have since removed it from their site. What they did not do is replace it. Thus, I am left to achieve on my own what appears to be the most efficient manner, or resign myself to what now appears to be prohibited. I have since been told, by the way, that indirect access via HTTP requests is common procedure. Considering, however, that the Matomo application and my web application both lie on the same server in the same document tree -- albeit under different add-on domain names --, it seems unreasonable to have to make HTTP requests to achieve my reporting goals. In the Matomo forum set up for Matomo users Matomo appears to have adopted a stance of silence on this matter. It is for this reason that I have taken it up with W3Schools. Roddy
  7. It is configured, but the file in question does not respond as hoped. <?php echo date("r"); ?> Roddy
  8. Dear Kayut! You wrote: I provided you with a solution to your problem. Your gratitude: It does have much to do with the solution to your problem, however. This is the forum for jQuery, as are most forums dealing with Javascript. Your goal is to iterate across a series of div elements that share a common class. I provided you with the easiest solution of which I am aware. Hopefully you have read and understood well Ingolme's explanation, for it is unlikely that you will ever receive another response from me. To everyone else, when I think of order, I think in terms of multiples of 10. For example, two orders of magnitude would be some number of a 100 times faster. For the forum membership please see measurethat.net. jquery_vs_js.tiff
  9. Hi, Kayut! The w3school Team appears to be on vacation. Have you tried jQuery? It is reformatted Javascript. So you can easily intermix the two. Below is all you need. <script> $(".demo").css("border","1px solid red:); </script> Roddy
  10. iwato

    How to Prepend Zeros to a Numerical Value

    Dsonesuk: Even something else? Roddy
  11. BACKGROUND: Recently I learned how to embed directly a Matomo widget into my website. Although there are several ways to make this happen, I am only able to achieve two of them at this time: one, gives all autonomous users access to all Matomo's reporting widgets and a large number of reporting methods; the other, exposes the superuser's authorization token that would leave a disastrous breach in database security. DILEMMA: Although I am able to retrieve the widget via CURL in an invisible PHP file, and consequently embed the widget's contents via the src attribute of an iframe, I am not able to do so with the same rich formatting that can be achieved when the same HTTP request is placed directly into the src attribute of the iframe. Either cURL is stripping away valuable information or the Browser is unable to process the information provided in the format provided. QUESTION: What must I do in order to get cURL to behave in a manner that produces information compatible with an ordinary web-browser? Roddy
  12. iwato

    How to Prepend Zeros to a Numerical Value

    I understand the nuance, but I am now confused about the prototype property. Is it a single property with only one value, a single property with many values -- say, an array --, or something else. Roddy
  13. JSG: You are correct. Removing the line breaks does perform a proper download and insert. What I usually do -- unformat my HTTP requests before sending -- I did not do in this case. I was falsely led to believe by own implementation that it would not make a difference. Indeed, the same that works in an HTML document with the correct headers, does not work in a PHP file with no headers. Which brings me to my next question. How must I set the PHP header function to insure that the downloaded content is properly formatted into the src attribute of the iframe? Among other things the CSS styling and images are missing. The link functionality is also lost. In the meantime I was able to discover that the content-type of the returned data is text/html; charset=utf-8. I was able to discover this via the using the CURLINFO_CONTENT_TYPE option suggested by the furtive fox. Please understand that what I am requesting is a Matomo widget designed to display a certain body of dynamic knowledge that includes various kinds of images ranging from icon highlighting to functional maps. One further thought, once the proper MIME-TYPE is discovered where should it be entered? In the requesting CURL, at the top of the PHP document that is making the request, or somewhere else. The browser is obviously doing something that CURL is not. Roddy
  14. Matomo allows three channels of external access to the Matomo program: piwik.php (644), piwik.js (777), and the bot request text file whose name I do not remember. Each of these channels is accessed via an HTTP request (secure or unsecure, with the option to enforce security). The piwik.js channel is for webpage data collection. The piwik.php channel is used for data reporting. The superuser who logs in with his name and password has the authorization to permit anonymous users unlimited access to Matomo's reporting API (read piwik.php). He can also specify named users. Whether an anonymous or named user the privileges are the same -- unlimited use of the reporting API. I do not wish to offer unlimited use, rather, restricted use. Unfortunately, within the current configuration I have no way of granting restricted autonomous use. It is nothing or everything for everyone or the same for a select number of users. All of the critical user information is located in a folder called config. This folder is a sibling with all other Matomo files and folders located in the Matomo package. Inside the config folder is a .htaccess file. Eliminating this folder provides me with the access needed to manipulate the files and folders of Matomo without having to make HTTP requests. In effect, the Matomo package and the Grammar Captive website are located in different branches (add-on domains) of the same root directory. It seems obvious that the just mentioned .htaccess file is critical to integrity of the Matomo package. It is the guard dog to the entire PHP package. I need to set the biscuit that will silence the dog as I pass in and out, else I will have to perform all of my commands through HTTP requests, and even is already causing trouble as can be seen through another W3Schools posting. Roddy
  15. iwato

    finding elements with data- attributes

    Have you tried .attr(data)? Roddy
  16. So, I replaced the curl_exec() statement with the following if(curl_exec($curl_request) === false) { echo 'Curl error: ' . curl_error($curl_request); } else { echo 'Operation completed without any errors'; } curl_getinfo($curl_request, CURLINFO_REDIRECT_URL); and received the following at the bottom of the log-in page that appears in the iframe. Operation completed without any errors CURL is happy, but I am sad and must soon go to bed. Roddy
  17. Yes. Good call. Unfortunately, the problem is not resolved. For, where before there was nothing, it is now asking me to log in, as if I were going through the frontdoor. Keep in mind, the only difference between what I am trying to do above and what is already working on the same page is what I have already explained. In the first instance the loading of the iFrame content is indirect; in the second instance it is direct. So, I added the following two lines of code to my PHP file: curl_setopt($curl_request, CURLOPT_HTTPAUTH, CURLAUTH_ANY); curl_setopt($curl_request, CURLOPT_USERPWD, "[...]:[...]"); with the required name and password. Unfortunately, nothing changed. Any idea as to why cURL is being rejected? Roddy
  18. Nothing appears in the frame. What follows is the code. My last experiment among several. The iFrame <iframe id='dashboard_map' src='./widget_map.php'></iframe> The PHP (widget_map.php) <?php ini_set('log_errors', 1); ini_set('error_log', dirname(__FILE__) . DIRECTORY_SEPARATOR . 'error.log'); ini_set('html_errors', 0); ini_set('display_errors', 0); error_reporting(E_ALL); $url = 'https://www.nudge.online/_utilities/php/matomo/index.php ?module=Widgetize &action=html &widget=1 &moduleToWidgetize=Live &actionToWidgetize=widget &idSite=1 &period=day &date=yesterday &disableLink=1 &widget=1 &token_auth=...'; $curl_request = curl_init(); curl_setopt($curl_request, CURLOPT_URL, $url); curl_setopt($curl_request, CURLOPT_RETURNTRANSFER, 0); curl_exec($curl_request); curl_close($curl_request); } ?> Now, the same URL provided above works if embedded directly into the iFrame. Roddy
  19. I have already spent several days. I know enough to know that something is possible, but in this case do not know enough to do it myself. Security has rarely been an issue for me, because up until now my livelihood has not depended on it. I humbly disagree with you about the GDPR and the NSA. I know of know government that does not wear two faces: one of benevolence, and the other of power, control, manipulation, and self-interest. The GDPR is a show of unneeded protective benevolence to cover for what is truly going on behind the scenes. You are naïve to think otherwise. If the EU cared, then it would educate the European public about the reality of data collection and not interfere with private enterprise. There are enough laws on the books already to handle the problem of identity theft and the abuse of private information. Roddy
  20. iwato

    The best way to instantiate a new object

    Does it not depend on the problem that you are trying to solve? The second example simply creates an object with two properties and assigns a value to each. The third example creates a function that fixes the value of one of the properties, allows you to assign a value to the other property, and provides a means to recover the information about both properties via a function that you can assign to the newly created instance. If I have properly understand your intention, rather than your words, a better comparison would be var theDude = { name: "David", age: 20, }; and function Person (name, age) { this.name = name; this.age = age; } var theDude = new Person("David", 20); In which case you are left with the same question. What is the intended purpose of creating the object? In both cases you are creating an object that you are assigning to a variable called theDude. Now, why would you prefer one over the other do you think? Roddy
  21. iwato

    array in mysqli query

    Make sure that $result is not empty. Enter $result = $stmt->execute($uniqueValueArray_id); below $result = $stmt->execute($uniqueValueArray_id); and make sure that $result is not empty. Also make sure that you are using the proper fetch-style. I do not use PDO, so I cannot help you any further. Roddy
  22. It took some time to find it, but I was finally able. Unfortunately, I was unable to find anything in Chrome, and I have long since given up on Safari, as it is next to useless in my current operating environment. The following is the procedure used to display the structure and contents of a result object that is generated in a PHP file called with an AJAX request. Open the Firefox Console and find the Network tab. While in the Network tab find the javascript (.js) file responsible for calling the PHP file that generates the JSON object. Highlight the file by clicking on it. While the file is still highlighted click on the XHR tab. This will cause the relevant .php file(s) to appear below the highlighted .js file. Click on the PHP file of interest and find the Response tab in the appropriate corresponding box. It is in the viewport of this box that the object appears. Click on the various objects, arrays, and other components of the object to learn how it is structured and to display the values. Have a great weekend! Roddy
  23. DILEMMA: I have a fairly complex JSON object that is introduced via an AJAX call. Unfortunately, my control panel tells me that it is undefined. Is this because it has no value? Or, is it because I do not know how to read the value properly? {"lastVisits"[{"firstVisit":{"prettyDate":"Monday, May 14, 2018"}}]} The name of the variable into which it is read is visitor_data. Am I reading the value of correctly? visitor_data.lastVisits[0].firstVisit.prettyDate Roddy
  24. iwato

    How to Prepend Zeros to a Numerical Value

    So, in conclusion, .pad(size) is a user-created method of a primitive Number object that is called via the Number.prototype property and executed by either the parentheses operator or variable assignment. Do I have everyone's agreement. Roddy
  25. iwato

    Dysfunctional Dynamically Introduced Stylesheet

    Oh well, infinity wins out. For, it is only bounded by the imagination, and it seems to be without end. At least, until I die, and someone else's carries on. Roddy