Leaderboard
Popular Content
Showing content with the highest reputation on 07/22/2019 in all areas
-
A client hired a security consultant to do a site analysis and they advised that the X-Content-Type-Options HTTP header should be set to "nosniff". The MDN docs for this header say: "Site security testers usually expect this header to be set." https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options This was easily resolved by adding the following to .htaccess Header set X-Content-Type-Options "nosniff" Do you think it would be good to add this to the default PW .htaccess file?4 points
-
Hi @mr-fan, you are dealing with a very interesting project! Wow… it brings me back to my previous lives in Microcontrollers and Nand Flash storage... If your MCU timer is sampling analog data every 10 minutes, and your objective is to store them for 5 years at this granularity level (10 minutes), as you have calculated, it means 2.6*10^5 records. That's not trivial at all. I love PW page-storage capabilities, but, on my personal opinion, resulting storage solution would be less efficient and performant than directly storing data into a MySQL table. I would use MySQL table for data storage and PW pages for data post-processing and reporting. A lot would depend from which kind of post-processing you are going to need, but as you are building a simple (but big!) data logger, another option for storage could be even to create a simple flat file to which you are appending a new record every 10 minutes. However MySQL, in the long run, will give much better flexibility, versatility, and performance. If you wish to look for a simple example of using MySQL from inside PW I suggest you to explore at FieldtypeComments core module. Comments in PW are not made using PW page-storage, but as a MySQL table (field_comments) so you can get some useful hints in dealing with MySQL schemas from within PW. Of course you do not need to create a separated MySQL database for your logger, it can be simply a new table inside your existing PW database, exactly as PW does to manage comments. Please also note that PW library provides an embedded support for dealing with MySQL (I did not use it so far, but .. now I feel I need to make a trial soon…) in $database API variable. By the way, if you need any help to create a MySQL data logger table inside your PW database, just give me the data specs, I would be glad to help you in setting up a trace. Wish you a nice week-end.3 points
-
Hello Fellow PW fans. Tought i share a simple but usefull way of utilizing the $log system in PW to do simple loging on what IP visit the site and also the HOST. Its not fancy, and its very basic, see it as a boiler plate. You can get all kinds of fancy with it. Remember that the $log system automaticly records the URL from where it was called so we don´t need to supply that to our Entry. I just wanted a simple entry with IP and HOST, the date is also recorded with the entry automaticly. The beauty is that i can watch the logs from the ADMIN page almost in realtime. I am using the "markup regions" output method so i put the code in my _main.php file. You could just put it wherever like to be included with every page load in your site. I hardcoded my logfile to be named ip_log_site but you can use what you feel is better. Also made sure the loging do not happen if your logged in as admin (Super user). See this PW Doc for more info: https://processwire.com/api/ref/wire-log/save/ <?PHP function logIP($session, $log) { /* get IP info */ $ip_adress = $session->getIP(); $host_address = gethostbyaddr($ip_adress); /* log IP adress info NOTE: 'ip_log_site' is a hardcoded name of the logfile, change for your preference. */ $log->save("ip_log_site", "IP: {$ip_adress}, Host: {$host_address}"); } /* if Super User (Admin) do not log */ if(!$user->isSuperuser()) { logIP($session, $log); } ?> Hope anyone have use for it. /EyeDentify2 points
-
Hello folks, Your voice can also be heard: https://hacks.mozilla.org/2019/07/mdn-web-developer-designer-survey/ "The survey results will be published on MDN Web Docs (MDN) as an annual report. In addition, we’ll include a prioritized list of needs, with an analysis of priorities by geographic region."2 points
-
Thanks for sharing this, EyeDentify – nice and simple ? Just a little note before folks go implementing IP logging: IP addresses are considered personal data, and as such you should keep GDPR (and similar legislations) in mind. Here's SE question that covers the details related to logging IP addresses: https://law.stackexchange.com/questions/28603/how-to-satisfy-gdprs-consent-requirement-for-ip-logging. (The general consensus seems to be that you don't need to ask for permission before logging IP addresses, but there are other requirements you do need to keep in mind.)2 points
-
I like the developer satisfacion coming through these lines ?2 points
-
This is included with the default .htaccess file, but disabled by default. See section "4. Protect from XSS with Apache headers". It seems to me that this should probably be enabled by default, but I'm guessing that it was left disabled for a reason – @ryan would be the best person to say if those reasons still apply.2 points
-
Thanks for all input again. Again i was not to clear - single project just for me and just for information no public hits no further usecase for the system. Yes LostKobraKai i think i did'nt plan on this one...until now i didn't have such a usecase or wasn't deep into database performace (what is not really needed for normal websites if you use PW as a base...it scale for this cases and i know that well) So may i am a little bit to naive on this project - and my feeling said "Hey try to ask the dev guys in the forum for hints" ...;) I would first go the hard way and make my hands dirty and will try how far PW could go on this one.... Yes nested page setup like metioned wont scale on things like "live aggregating" all saved data, but i think i would be happy if i could get things like average of year/month/week and store them in separate fields on the dedicated template - so like netcarver wrote if i am modest in granularity it will run fine. But a important Tipp is the FieldtypeEvents module from Teppo, i forgot this one - it would work great for the week dataset so many pages are spared. What i will try with dummy data is now: templates /station/year/month/week station (id, title) year (id, title, temp, humidity, pressure, rain, light) - the average - average from 12 childpages should be no problem month (id, title, temp, humidity, pressure, rain, light) - the average - this will end in 52 childpages for a join for the average week (id, title, records - modified eventtype field for the intraday records) - this will end in 672 entries (if i take a record every 15 minute) in one week field Problems on this one would be selecting from date to date but i would be fine with averages of weeks or months...and maybe the amount of fieldtypeevent tables (52 per year)? I don't have the time to investigate in other DB systems, since this year i've got one more little maid that take over my speartime ? But with your interesting input i can think i get in the right direction, and don't have wrong views on aggregation and reporting of the collected data. Since alle of you pointed out that the collection wouln't be the problem with PW or MySql....but all the other stuff. And on these points i could make compromise since this is only a hobby project. I will report (even if it took a while). Even on such rare and offbeat questions in this forum you get helpfull and friendly answers! You all made my weekend! - I love this forum, it is a hidden island in the www2 points
-
Absolutely agree with this – use case for the data matters a lot! In my experience MySQL queries (with decent indexes) tend to be pretty fast until you reach the scale of millions of rows, but if this is going to be a public-facing service that gets a lot of hits and needs to generate all sorts of reports real-time then definitely consider alternatives right from the get-go. Might be a good idea to look into them anyway, but if it's a one-off project and you're likely to stay in 200-300k record range, you're probably not going to get a major benefit out of them. That being said, if you already know what your data is going to look like, you can take some guesswork out of the equation by starting from a simple proof of concept: create a database table for your data, add a script that generates some 200-300k rows of random mock data based on your actual expected data format, and build a proof of concept graph to display said data. If the database concept doesn't pan out, i.e. it's too slow or something like that, you can just swap that to something more performant while keeping other parts of the application. Either way it's often a good idea to build your product in layers, so that if a specific layer – graph library, database, or something in-between – needs to be swapped for something else, other layers remain more or less the same ?2 points
-
Example implementation: Info: So this is very much an ALPHA version of what I hope turns into a swiss armory knife payment module. Currently you are able to take payments with the payments form or cross browser payments button (Apple Pay etc). Please read implementation details here and consider contributing https://github.com/benbyford/PaymentStripeIntents TODO: Add subscription functionality Add customer functionality More testing and code clean up More usage examples anything else?1 point
-
DEPRECATED! I'll release a commercial module "RockGrid" in 2023/2024. If you are interested please write me a PM ? ---------------------------------------- This module is (or will be) the successor of RockGrid. It uses http://tabulator.info/ as grid library that is completely open sourced (MIT, no commercial extensions) and as far as I've seen so far at least as powerful as ag-grid, which RockGrid is using. GOALS: Support various data sources (RockFinder, JS, PHP, SQL) Supported only in PW Backend + Uikit Easy setup of new fields DOCS: Currently the readme is terrible, sorry for that. But you get lots of examples after installing the module! From simple tabulators to more complex ones. INSTALLATION: Just install the main module. RockMarkup is a required dependency. Please also have a look at the RockMarkup examples before jumping into RockTabulator! STATUS: The module is early alpha and can be downloaded from github: https://github.com/BernhardBaumrock/RockTabulator It took me two weeks of rewriting RockMarkup/RockTabulator to get where I am now and I think I'm quite happy with the setup. There might be some breaking changes though in the near future. At the moment the main features that should be working properly are: Data sources: SQL, PHP, JS Sandbox for easy setup Multilang This means basically everything that is possible with Tabulator is also possible with RockTabulator. Though, there are no custom helpers/plugins yet. That's the next step and whoever is willing to help, please give me a shout ? If you have any questions or ideas please let me know ?1 point
-
Please don't use this module any more. I think in the end it just adds more complexity (and dependencies) than benefits. See this tutorial how simple it is to create a custom runtime-only Inputfield: WHY? I've started building this module because the existing solutions by @kongondo and @kixe (https://modules.processwire.com/modules/fieldtype-runtime-markup/ and https://github.com/kixe/FieldtypeMarkup) did not exactly fit my needs. Actually this module is aimed to be a base module that can easily be extended by other modules. It takes care of the heavy lifting that has to be done when working with custom fieldtypes in ProcessWire (injecting scripts and styles, handling JS events, doing translations). See RockTabulator as an example. I'm quite sure more will follow (eg ChartJS)... WHAT? This module helps you injecting ANY php/html/js/css into any PW backend form (either on a page or in custom process modules). It also comes with a sandbox process module that helps you setup your fields and provides handy shortcuts that integrate with TracyDebugger and your IDE: WHERE ...to get it? At the moment the module is released as early alpha and available only on github: https://github.com/BernhardBaumrock/RockMarkup2 If you have any questions or ideas please let me know ? PS: This module shows how easy it is to extend this module for your very own needs. All you need to do is providing the module's info arrays and then overwrite any methods that you have to modify (eg the InputField's render() method): https://github.com/BernhardBaumrock/RockMarkupExtensionExample1 point
-
Glad to hear that the error has disappeared ? The problem might've had something to do with your environment, but the resulting error is an interesting one. In this case something attempted to change current working directory into one that wasn't allowed, so PHP threw an exception – and since throwing exceptions from __toString() is not allowed, that resulted in fatal error instead. This seems like an unexpected result, so it might be worth investigating if it can be avoided, though I'm not sure if there's any sensible way around this. As long as __toString() does anything even remotely complicated, there's a risk of running into this issue.1 point
-
If it's just styling, you should first try a CSS-only solution. You can do a lot with just :nth-child or flexbox.1 point
-
Thank you, i didn't know that. I solved my problem by deleting all existing images in the field with $imgfield->remove($image); before saving the new one with setAndSave()1 point
-
Thx Robin ? Didn't know that, just tried it and it also works for $files->include() ?1 point
-
Make sure that the translated versions have the %d placeholder as well – from your description it seems likely that they don't.1 point
-
Hello @LostKobrakai I have written a class for creating tables. The first class is the table class itself. The second class is a class for creating table-cells (the content of the table of course). Both class extends from the same parent class (a wrapper class). So both use the same methods from the wrapper class (in this case methods for setting attributes like class, id,...) My aim was to chain methods from the table-cell class inside the table class. My OOP-code of creating a table looks like this in this case: $table = ( new \UikitClass\Table(3))->setCaption('Beschreibung'); //thead $table->addHeaderCell()->setModifier('expand')->setText('Spalte 1')->setClass('thclass'); $table->addHeaderCell()->setText('Spalte 2')->setClass('custom'); $table->addHeaderCell()->setText('Spalte 3')->setClass('custom'); //tbody $table->addCell()->setText('Text 1'); $table->addCell()->setText('Text 1')->setClass('custom'); $table->addCell()->setText('Text 1')->setClass('custom'); $table->addCell()->setText('Text 1')->setClass('custom'); $table->addCell()->setText('')->setClass('custom'); //tfoot $table->addFooterCell()->setText('Footer')->setClass('uk-text-center')->setAttribute(['colspan' => '3']); echo $table->render(); So every chaining starts from $table for easier writing. Therefore I wanted to include the class of the table-cells inside the table class. In this case addHeaderCell(), addCell() and addFooterCell holding an object of the table-cell class and all methods after this affect the table-cell object. So I start with $table (table-class object), switch to the table-cell object (fe addHeaderCell() method), use methods to the table-cell object and add this to the table class. Maybe a little bit difficult to explain, but the idea behind was to make writing easier for the developer.1 point
-
In ProcessWire the wisdom usually is to avoid selecting much data at all. That's the sole reasoning for e.g. the nesting you described. It won't help at all if you want to aggregate over e.g. the last 5 years of weather data. The biggest question still open in this topic is "what for?". Without knowing the patterns of how you intend to access the stored data and which timeframes of aggregations of this data are appropriate it's not really possible to tell what you need. If you're fine with reports taking a hot minute to aggregate you're in a whole different ballpark than if you need huge aggregations to be live and instantly available in some web dashboard. Especially if you plan to hit the latter case I'd also suggest looking at proper databases for time series data, especially if the number of entries is meant to grow beyond the ~500k–1kk mark. I'd look at influxdb or postgresql with timescale plugin. Using pages in processwire might make sense for a mvp, but if things should scale it'll be a lot of manual querying even in processwire, so I'd opt for the proper solution from the start. Given the volume of data I doubt you can avoid getting more intimate with databases, as you just need to aggregate data directly on the db side, which processwire doesn't support to begin with.1 point
-
Chaining (piping usually means something different) in OOP doesn't mean returning $this. It means return the object, which you want to execute the next method call on. Where you get the object to return from is up to you. But I'm really wondering what the use case behind this is. Generally I'd tend to avoid classes knowing of each other and rather opting for composing their functionality with code outside of them.1 point
-
Not sure how familiar everyone here is with the inner workings of ProcessWire, so just to expand on this a little bit: FieldtypeComments is a ProcessWire Fieldtype module, and Fieldtype modules can define their own database schema. The FieldtypeEvents module was built as an example for custom Fieldtype modules, and if you take a closer look at FieldtypeEvents::getDatabaseSchema() (and other methods in that class), you should get a pretty good idea of how this stuff works. On the other hand if you want to store loads of data and don't really need/want said data to be stored in an actual field (accessible via the API and editable in the Admin), you can also define a custom database table, just as Edison pointed out above. You can find some examples of working with custom database tables from the ProcessChangelog module. Of course you don't have to wrap the table creation etc. into a module – not unless you expect to set this thing up on multiple occasions ? One last point on naming custom tables: if you create a truly custom database table, you'll want to steer away from any native table names. This includes field_*, since that prefix is reserved for field data.1 point
-
1 point
-
There is some code and some links to explore in this post:1 point
-
Try: $wire->addHookAfter('Field::getInputfield', function(HookEvent $event) { $page = $event->arguments(0); $inputfield = $event->return; // Only for non-superusers if($event->wire('user')->isSuperuser()) return; // Only for a particular Repeater page ID if($page->id !== 1553) return; // Set collapsed to Inputfield::collapsedNoLocked or Inputfield::collapsedHidden as suits $inputfield->collapsed = Inputfield::collapsedNoLocked; });1 point
-
When you add an image via the API rather than via the inputfield you have to do all the work yourself that the inputfield would otherwise do for you. A recent answer to a similar question, which contains a link to some code that might be useful to you:1 point
-
@mr-fan What granularity of data do you need for things that are 5 years old? Do you need to drill down to get the exact temperature given a date and time from 5 years in the past? Or would an average do? If an average would be enough, then have a look at RRDTool. All you'd need to do is feed the data into it, then link the graphs it generates into your PW driven site. Although I've not used RRDTool for about 9 years, I ran it on a Raspberry Pi A (IIRC) to profile my house's thermal performance. I did this by collecting 1 minute temperature samples from a network of 8 x 1-wire temperature sensors I installed in the property. I ran this over a period of about 2 years, and all that data got squished into a fix-sized on-disk DB of a few megabytes. I used a cron job to pull the images from the graph generator and cache them on disk with fixed filenames. I had nginx serve a simple html webpage that referenced the images by name. Worked really nicely on my local network, but the output graphs aren't the prettiest. You might be able to feed the results into grafana or Bernhard's tool if nicer output is needed. If you do need high granularity of the old data, RRDTool isn't the tool for you. @dragan ESPs are a family of Wifi/Cellular capable microcontrollers. Very popular with electronics/systems makers. Example.1 point
-
@apeisa @Soma Just noticed that the modules directory entry for this module still points to the old repository, and also doesn't list Multisite as being PW3.x compatible. Would it make sense to update the entry to point to Soma's repository? We just did a similar shift for AdminBar, and Adrian made the necessary changes in the modules repo. Also, I'm currently not entirely sure which branch I should use – last I checked it seemed that "dev" was the one to use, but since then that has apparently been removed (or renamed) and now there are two branches left: master and dev2. Master is the one with most recent updates, so is that preferred over dev2, or vice versa? Sorry for all the silly questions ?1 point
-
The repos say they are unmaintained. For the Python lib they recommend https://github.com/mbloch/mapshaper as an alternative. For the JS lib they recommend https://d3js.org/ for the mapping and https://github.com/topojson/topojson instead of SVG as the data format.1 point
-
https://blog.theodo.com/2019/07/vscode-php-development/1 point
-
@ttttim - have a read of this: https://processwire.com/blog/posts/pw-3.0.135/#step-4-decide-whether-to-to-enable-hsts-section-9f1 point
-
@Markus (Blue Tomato) the showIf only works with fields and there values. AFAIK, the published / unpublished value cannot be used as condition for showIf directly in the template editor. But you may define a hook and set the visibility of that field within the hook. Here is example code as a starting point. You can use this in site/ready.php $wire->addHookAfter('ProcessPageEdit::buildForm', function (HookEvent $event) { // make sure we're editing a page and not a user if($event->process != 'ProcessPageEdit') return; // get page and form $page = $event->object->getPage(); $form = $event->return; // optionally check for matching template(s) with a condition if('mydesiredtemplatename' != $page->template->name) return; // get the field and conditionally set the visibility $form->get('yourfieldname')->collapsed = $page->isUnpublished() ? Inputfield::collapsedHidden : Inputfield::collapsedNo; $event->return = $form; return; }1 point
-
This reminds of something I did a while back. There's another way of grabbing the first item: Possibly a bit late to the party here but knowing an extra method can't hurt. http://cheatsheet.processwire.com/pagearray-wirearray/sorting-and-filtering/a-not-selector/ Nice mockup btw @mike621 point
-
Here's a short snippet for site/ready.php that hooks after ProcessPageEdit::buildForm and moves a regular field (named "testfield here") from the Content tab to Settings. The methods used are from the InputfieldWrapper class. <?php wire()->addHookAfter("ProcessPageEdit::buildForm", null, "moveFieldToSettings"); function moveFieldToSettings(HookEvent $event) { $form = $event->return; $field = $form->find("name=testfield")->first(); if($field) { $settings = $form->find("id=ProcessPageEditSettings")->first(); // Alternatively, find a specific field to insert before/after: // $settings = $form->find("name=template")->first(); if($settings) { $form->remove($field); $settings->append($field); // In the alternative, insert before or after the found field: // $form->insertBefore($field, $settings); } } }1 point