Leaderboard
Popular Content
Showing content with the highest reputation on 07/20/2018 in all areas
-
This week we’re going to discuss a new security feature that’s currently in development on the dev branch: 2-factor authentication. In this post we look at the benefits of 2FA, how it works, the coming implementation in ProcessWire, and more: https://processwire.com/blog/posts/2-factor-authentication-coming-to-processwire/7 points
-
@Ivan Gretsky -thanks; sure - in short: FieldDescriptionsExtended Enhanced field descriptions ProcessDocumentation Main function is to provide help pages in the admin which can be separate, and navigable; Since you can control the pages, it allows admins to have any documentation page open in a separate tab or window; contrasting to Admin Help, which has the help information either contextually on the Template (in a tab) or all in 1 process page inside an accordion. This module also allows editors to download a PDF of the help page for offline reading, as well as various other helpers. AdminHelp Original module, not being actively maintained, but soon all of the elements of this module would be covered by ProcessDocumentation. Still helpful if you want the simple help tab on a template, or some basic documentation for a site, all on 1 process page, in an accordion. ----- The next version of ProcessDocumentation will include a feature to show help content contextually on any template, using a help icon in the breadcrumbs bar instead of down in the editor tabs. In addition it will allow for showing expandable/collapsible help text at the top of any Lister/ListerPro. So in the end, ProcessDocumentation should cover most needs for fully documenting and providing help for any admin.3 points
-
Time for a little update. ? There are many changes again. Most visible: More Ajax, more Drag&Drop, more Wysiwyg. Real containers (Tree hierarchy) instead of "nested groups". Rows are also containers now. In this little video, I will show you how to layout a responsive page from scratch without writing a line of code. http://theowp.bplaced.net/upload/reptile.html This system is not for absolute noobs. You need to have an idea about how responsive web pages and Bootstrap work. But then one can be really fast I think. Still a long way to go, but I hope you like the idea. Thank you.3 points
-
I would still recommend the module that soma linked to - if it's just for Youtube or Vimeo videos, this is a much nicer approach than pasting in iframe embed code.3 points
-
@Soma Yeah this is my issue with Vue.JS - I use Vue.JS often for two way data-binding which is amazing to be able to easily update content and do visual changes to the site based on those updates. For example adding something to a basket. It's much easier with Vue than jQuery or JavaScript. My issue with Vue is exactly that. You can use it just on a component basis or you can use it to render your entire UI. To me it just doesn't make sense to use it to render an entire UI with a website. A web app sure, but a website it's often overkill and introduces that exact problem. You can introduce server side rendering of Vue with Nuxt but then it just seems like another layer of 'over complication'. I personally stopped using Vue for websites unless I absolutely needed two way binding. It just didn't make sense and the extra complication of implementing it such as having to convert everything from ProcessWire into a JSON feed. EDIT: Noticed this post still gets likes, so what's changed since then? AlpineJS. AlpineJS is a solution to this exact problem, worth a look for anyone wanting to do some cool UI stuff without including all of Vue features and overhead.3 points
-
Hi everyone, Here's a new module that I have been meaning to build for a long time. http://modules.processwire.com/modules/process-admin-actions/ https://github.com/adrianbj/ProcessAdminActions What does it do? Do you have a bunch of admin snippets laying around, or do you recreate from them from scratch every time you need them, or do you try to find where you saw them in the forums, or on the ProcessWire Recipes site? Admin Actions lets you quickly create actions in the admin that you can use over and over and even make available to your site editors (permissions for each action are assigned to roles separately so you have full control over who has access to which actions). Included Actions It comes bundled with several actions and I will be adding more over time (and hopefully I'll get some PRs from you guys too). You can browse and sort and if you have @tpr's Admin on Steroid's datatables filter feature, you can even filter based on the content of all columns. The headliner action included with the module is: PageTable To RepeaterMatrix which fully converts an existing (and populated) PageTable field to either a Repeater or RepeaterMatrix field. This is a huge timesaver if you have an existing site that makes heavy use of PageTable fields and you would like to give the clients the improved interface of RepeaterMatrix. Copy Content To Other Field This action copies the content from one field to another field on all pages that use the selected template. Copy Field Content To Other Page Copies the content from a field on one page to the same field on another page. Copy Repeater Items To Other Page Add the items from a Repeater field on one page to the same field on another page. Copy Table Field Rows To Other Page Add the rows from a Table field on one page to the same field on another page. Create Users Batcher Allows you to batch create users. This module requires the Email New User module and it should be configured to generate a password automatically. Delete Unused Fields Deletes fields that are not used by any templates. Delete Unused Templates Deletes templates that are not used by any pages. Email Batcher Lets you email multiple addresses at once. Field Set Or Search And Replace Set field values, or search and replace text in field values from a filtered selection of pages and fields. FTP Files to Page Add files/images from a folder to a selected page. Page Active Languages Batcher Lets you enable or disable active status of multiple languages on multiple pages at once. Page Manipulator Uses an InputfieldSelector to query pages and then allows batch actions on the matched pages. Page Table To Repeater Matrix Fully converts an existing (and populated) PageTable field to either a Repeater or RepeaterMatrix field. Template Fields Batcher Lets you add or remove multiple fields from multiple templates at once. Template Roles Batcher Lets you add or remove access permissions, for multiple roles and multiple templates at once. User Roles Permissions Batcher Lets you add or remove permissions for multiple roles, or roles for multiple users at once. Creating a New Action If you create a new action that you think others would find useful, please add it to the actions subfolder of this module and submit a PR. If you think it is only useful for you, place it in /site/templates/AdminActions/ so that it doesn't get lost on module updates. A new action file can be as simple as this: <?php namespace ProcessWire; class UnpublishAboutPage extends ProcessAdminActions { protected function executeAction() { $p = $this->pages->get('/about/'); $p->addStatus(Page::statusUnpublished); $p->save(); return true; } } Each action: class must extend "ProcessAdminActions" and the filename must match the class name and end in ".action.php" like: UnpublishAboutPage.action.php the action method must be: executeAction() As you can see there are only a few lines needed to wrap the actual API call, so it's really worth the small extra effort to make an action. Obviously that example action is not very useful. Here is another more useful one that is included with the module. It includes $description, $notes, and $author variables which are used in the module table selector interface. It also makes use of the defineOptions() method which builds the input fields used to gather the required options before running the action. <?php namespace ProcessWire; class DeleteUnusedFields extends ProcessAdminActions { protected $description = 'Deletes fields that are not used by any templates.'; protected $notes = 'Shows a list of unused fields with checkboxes to select those to delete.'; protected $author = 'Adrian Jones'; protected $authorLinks = array( 'pwforum' => '985-adrian', 'pwdirectory' => 'adrian-jones', 'github' => 'adrianbj', ); protected function defineOptions() { $fieldOptions = array(); foreach($this->fields as $field) { if ($field->flags & Field::flagSystem || $field->flags & Field::flagPermanent) continue; if(count($field->getFieldgroups()) === 0) $fieldOptions[$field->id] = $field->label ? $field->label . ' (' . $field->name . ')' : $field->name; } return array( array( 'name' => 'fields', 'label' => 'Fields', 'description' => 'Select the fields you want to delete', 'notes' => 'Note that all fields listed are not used by any templates and should therefore be safe to delete', 'type' => 'checkboxes', 'options' => $fieldOptions, 'required' => true ) ); } protected function executeAction($options) { $count = 0; foreach($options['fields'] as $field) { $f = $this->fields->get($field); $this->fields->delete($f); $count++; } $this->successMessage = $count . ' field' . _n('', 's', $count) . ' ' . _n('was', 'were', $count) . ' successfully deleted'; return true; } } This defineOptions() method builds input fields that look like this: Finally we use $options array in the executeAction() method to get the values entered into those options fields to run the API script to remove the checked fields. There is one additional method that I didn't outline called: checkRequirements() - you can see it in action in the PageTableToRepeaterMatrix action. You can use this to prevent the action from running if certain requirements are not met. At the end of the executeAction() method you can populate $this->successMessage, or $this->failureMessage which will be returned after the action has finished. Populating options via URL parameters You can also populate the option parameters via URL parameters. You should split multiple values with a “|” character. You can either just pre-populate options: http://mysite.dev/processwire/setup/admin-actions/options?action=TemplateFieldsBatcher&templates=29|56&fields=219&addOrRemove=add or you can execute immediately: http://mysite.dev/processwire/setup/admin-actions/execute?action=TemplateFieldsBatcher&templates=29|56&fields=219&addOrRemove=add Note the “options” vs “execute” as the last path before the parameters. Automatic Backup / Restore Before any action is executed, a full database backup is automatically made. You have a few options to run a restore if needed: Follow the Restore link that is presented after an action completes Use the "Restore" submenu: Setup > Admin Actions > Restore Move the restoredb.php file from the /site/assets/cache/AdminActions/ folder to the root of your site and load in the browser Manually restore using the AdminActionsBackup.sql file in the /site/assets/cache/AdminActions/ folder I think all these features make it very easy to create custom admin data manipulation methods that can be shared with others and executed using a simple interface without needing to build a full Process Module custom interface from scratch. I also hope it will reduce the barriers for new ProcessWire users to create custom admin functionality. Please let me know what you think, especially if you have ideas for improving the interface, or the way actions are defined.1 point
-
Admin Theme Boss A light and clear theme based on Uikit 3 Features Five unique color options Beautifully redesigned login screens Modern typography using Roboto Condensed Extended breadcrumb with edit links Extends AdminThemeUikit, so you can continue using all current and future AdminThemeUikit features Option to activate theme for all users Compatibility with AdminOnStreoids and other third party modules Updated and Releases There is a shiny new release page where you can subscribe to updates for new releases of AdminThemeBoss. Color Variants: ProcessWire Blue Dark Black Vibrant Blue Happy Pink Smooth Green *new with 0.6.1* Requirements Requires a current ProcessWire version with AdminThemeUikit installed and activated. Installation Make sure AdminThemeUikit is activated Go to “Modules > Site > Add New“ Paste the Module Class Name “AdminThemeBoss“ into the field “Add Module From Directory“ Click “Download And Install“ On the overview, click “Download And Install“ again… On the following screen, click “Install Now“ Manual Installation Make sure the above requirements are met Download the theme files from GitHub or the ProcessWire Modules Repository. Copy all of the files for this module into /site/modules/AdminThemeBoss/ Go to “Modules > Refresh” in your admin Click “Install“ on the “AdminThemeBoss“ Module1 point
-
1 point
-
DEPRECATED - USE ROCKMIGRATIONS INSTEAD I'm very happy to share my newest module called "ProcessWire Kickstart" that I developed during the holidays Maybe some of you already saw the preview thread about this... What it does: This module makes it possible to install ProcessWire in a fully automated process. You can define all necessary settings in one single php file and you can even define "recipes" that get executed after installation. This means you can install modules, adopt settings and do whatever you want with your new site using the PW API (like creating pages and so on). You could also place a kind of frontend boilerplate on your git account and grab that after installation and place it in your templates folder. I ran out of time so maybe someone could try that out and show how he did it Additional to that there is a ProcessModule to install in your ProcessWire admin which makes creating and testing recipes super easy. Note: Alpha realese until this module gets some more testing. Please be careful with this tool since it does some heavy file system manipulations (unzipping, moving and DELETING whole directories...). Use at your own risk. Usage: Just grab a copy of the kickstarter, place it on your server, visit yournewsite.com/kickstart.php, adjust settings (like username+password) as needed and hit "install". If your mysql user does not have the rights to create a new database then you have to create a database before running the installer! Download: via SSH: cd /var/www/yournewsitedirectory wget baumrock.com/kickstart.php // or using curl curl baumrock.com/kickstart.php -L --output kickstart.php Manually: Klick baumrock.com/kickstart.php and upload the file to your server Note: baumrock.com/kickstart.php returns the current master file from the gitlab repo and changes the namespace of the script so that it can install itself via recipe. If you don't need to install the kickstart processmodule via recipe you could also download the kickstart.php file from gitlab. Screenshots/Walkthrough: The initial Screen: You can either upload a file via the left panel or take my example file from the gitlab repo: This way you can create your own kickstartfiles and host it on your own accounts. When the file is loaded you can easily edit all necessary informations, like username, password and the url where to grab ProcessWire from. I just tried it with an old version as well... 2.7 worked just fine (having the old installer that recently was updated) but an ancient 2.2.4 version failed. I don't think anybody will ever need to install lots of old versions of pw with this tool but I wanted to mention it here. Hit "install" and lean back - on my VPS it takes 15 seconds to install my very own custom version of processwire with all modules that i need After logging into your admin you'll see that all modules from your recipe are installed: Recipe Editor: As recipes are executed after processwire was installed you have all your API magic available there. Running this scripts is only possible inside of a working processwire installation, so I created a module to help you with that task. See the comments of the sample recipe for more information! I hope this tool helps you to save lots of time and create lots of awesome ProcessWire websites I would be happy to see how you use this and please share useful recipes here in the thread so that everybody can profit. Maybe you just want to throw in an idea what could be done (for example I can imagine a recipe that checks file permissions on the system after installation)... Some parts of the code and maybe also part of the idea are taken from @Soma 's old and still great online installer, thx for that!1 point
-
@adrian I guess it will vary. I can't see people with smallish brochure sites wanting it. However, I'm currently using PW to build an admin system for a charity. Most of the users are probably using their (child|spouse|pet)'s name + a year of birth as their password, yet they are trusted to handle their own client's confidential information on the system. I see 2FA as a big win for this kind of user, as a small change in log-in protocol can bring in a big benefit for the charity and its clients, by mitigating the risk of such poor passwords.1 point
-
Thanks Ryan! While I think this is a great idea in principle, I can't honestly see any of my clients wanting to use this. I guess at least protecting superuser accounts will be a nice improvement. Does anyone else think this will be a hard sell to clients, or do you think they will be really keen to use it? Maybe I need different clients ?1 point
-
Is mod_security enabled in the web server? If yes, it would be the first suspect.1 point
-
Hi, @tpr As you may already know, we have Restore tab in page edit, so selectors to hide should be updated with '#_ProcessPageEditRestore, #ProcessPageEditRestore, ' (in .module and with #ProcessPageEditRestore in .js). Also, where in the source are #_WireTabDelete and #WireTabDelete? (I wrote you a PM but I guess you didn't get a notice...)1 point
-
Neither I have an immediate need for rewrite in pure JS but I'm sure I'll try this on a new PW project (nothing in sight btw). I can have a look at it on next week if all goes well.1 point
-
Seems like a nice addition to your in-place documentation module suite, @Macrura: + I think that with PW in-place docs are a real help for editors. And you are the expert in this field. I would love to read or watch a screencast about all those modules used together. If you could find time to share your knowledge, that would surely be an awesome gift to the community. And yes, that is just a fancy way to ask something free for myself ?1 point
-
Hi @netcarver - ok thanks for the report; i'll have to investigate this with ajax opened fields, have not used those much, and didn't test; hopefully it will be a simple fix...1 point
-
Just used your module for the first time. It works great and I like that I was able to change (edit) the terms and the ability of users to save/review their settings.1 point
-
1 point
-
I think I found a little glitch in the module. I've installed the module within a subdir based pw instance. Then the module won't find the nessecary js and css files. The field shows on the page edit page only a blank value and not that it find's no data. I fixed it - for me - with the following change at line 64 in file site/modules/FieldtypeRockGrid/FieldtypeRockGrid.module.php: After that it seems to work for me. Many thanx for the great module!!!1 point
-
Nope: That doesn't help since you are finding the tasks, not the projects. So instead of creating a new PageArray you better create a normal PHP array $matching_project_IDs and add the IDs of the matching projects: $matching_project_IDs[] = $task->parent->parent->parent->id;1 point
-
If you have really many projects, to avoid loading them all into memory you should use findMany() instead of find().1 point
-
@Macrura - I decided to take a different approach with this. Now all the issues I noted above are no longer relevant. Please grab 1.0.4 and let me know how it goes.1 point
-
I don't know if this is the right place, it's not really a tutorial, just a tip based on notes I wrote myself in a recent project to get it straight in my own head. I thought it might be useful for others in a similar situation. Scenario: Create a search function that will search for keywords "foo" and "bar" in multiple fields, but the keywords do not have to be adjacent, in order, or even all in the same field. For eample, the selector must match if "foo" is in "field_a" and "bar" is in "field_b" -- so long as both keywords are present somewhere, the page match is valid. It is possible to just split the terms and do multiple queries on each field separately and then combine the results into a single PageArray for pagination (I believe there is a module that helps with this). However, I wanted to see if it was possible to do a basic version with a single query. Not The Solution: The following selector does not work when keywords appear separately in different fields (operator '~=' - contains all the words): $selector = "title|field_a|field_b~=foo bar"; What the selector is saying: FIND BOTH "foo" AND "bar" IN title OR FIND BOTH "foo" AND "bar" IN field_a OR FIND BOTH "foo" AND "bar" IN field_b In this case, both "foo" and "bar" have to be in the same field (but not adjacent or in order) to match. The Actual Solution What we need to use is "named selectors" to let us match each individual keyword separately while still using one selector. Using the same example as before: $selector = "selector1=(title|field_a|field_b~=foo), selector2=(title|field_a|field_b~=bar)"; What the selector is saying at its most basic level: FIND BOTH selector1 AND selector2 Or, to expand on this, it is saying: (FIND "foo" IN title OR field_a OR field_b) AND (FIND "bar" IN title OR field_a OR field_b) Crucially, "foo" and "bar" do not have to be in the same field to match. Practical Method In this example code, I am actually allowing the search for phrases (using "quoted text") as well as individual terms, so a person could enter... "foo bar" baz ... and it will keep "foo bar" together aa one term and "baz" as a separate term and match them as an exact phrase. // Keywords obtained from $input->get and cleaned (multiple spaces removed)/sanitized etc. $keywords = '"foo bar" baz'; // Split into individual search terms by space (preserve spaces in quoted text) $terms = str_getcsv($keywords, " "); // array("foo bar", "baz") // Build up named selectors $ns = ""; // named selectors string $i=1; // named selector count foreach ($terms as $term) { // operator '*=' - contains the exact word or phrase $ns .= ", ns{$i}=(title|field_a|field_b*=" . trim($term) . ")"; $i++; } //$ns = ", ns1=(title|field_a|field_b*=foo bar), ns2=(title|field_a|field_b*=baz)" // Construct the whole selector (modify/add other general selectors as needed) $selector = "template=my-template, limit=20, sort=-date" . $ns; // Find pages based on selector $results = $pages->find($selector); DISCLAIMER I haven't done any tests to see if this method is more efficient than running queries on each field separately and combining the results, I just wanted to see if it was possible!1 point
-
Given your Page Tree structure, the following should be possible - assuming the Tasks have a common task_template with the field assigned_to_user: $matching_tasks = Spages->find("template=task_template, assigned_to_user=user1"); Smatching_projects = new PageArray(); foreach ($matching_tasks as $task) { $matching_projects->add($task->parent->parent->parent); };1 point
-
1 point
-
I was all set to suggest that you do this: but apparently the Sanitizer::translate option forces lowercase (https://github.com/processwire/processwire-issues/issues/643). Here's another interesting thing I just found: https://github.com/processwire/processwire-issues/issues/644 which doesn't seem expected to me. If Ryan agrees that the first one is a bug, then the alpha sanitizer with translate should result in this:1 point
-
Thank you @adrian for confirming. I have opened a issue. ? https://github.com/processwire/processwire-issues/issues/6421 point
-
Great work! I prefer the default uikit theme but just gave it a try and everything worked. Here's a kickstartfile if you want to use PW Kickstart to try it out quickly using PW Kickstart:1 point
-
To get the repeateritems when they do not live on the current page, you do: $upcoming_dates = $pages->get(ID-of-repeaterpage)->agendaitem->find("agenda_datum>=$today, sort=agenda_datum"); and you go from there.1 point
-
I've put in a feature request for this on GitHub: https://github.com/processwire/processwire-requests/issues/2071 point
-
Something like this can help you, maybe you'll find their payment method: http://omnipay.thephpleague.com/gateways/community/ https://packagist.org/?query=cryptocurrency1 point
-
Some crypto currency payment methods. They integrated with WooCommerce. I could probably move from WooCommerce to SnipCart and Stripe easily enough but the crypto part wasn't feasible or something I really wanted to support right now.1 point
-
Turns out it's only an issue when I have this module installed: http://modules.processwire.com/modules/restrict-multi-language-branch/ Although that module works by setting the template noLang flag so I expect the same issue could also be replicated by setting that for a template, so I do think this needs some attention still.1 point
-
Just give him 2 offers. One for realizing his project on Wordpress, one for realizing it on Processwire. Show him the initial costs for the realization and also approximate maintainance costs. Make Wordpress a lot more expensive, of course - then he has "real data". Sorry for that comment. I know it's not that easy. I'm just a little annoyed by such statements, and I hope you get my point ? It's like asking "I want to go on vacation, which car is the best?". Good luck for googling that and getting a good answer with "real data"... It's not always about finding the right answers to the wrong questions, it's sometimes a lot more about asking the right questions ?1 point
-
I don't see a newsletter field ? but normally you'll find it in /site/templates/ and there should be a "_main", "_footer" or something with the layout in it (you can use own filenames here...)1 point
-
1 point
-
If you disable loading FEEL css, then you have unstyled <a> just like you want it, no need to override anything. That's why I requested this option, so I have full control of button styles. And as a bonus, you also have control of lightbox appearance ...1 point
-
The latest changes to the CSS broke my edit buttons ([data-feel]). Now I know, I could just override them, (what I technically do) but since these are of a higher css-specify I would need to make the css selectors stronger. Your CSS even includes an !important ? Would it be possible to disable button styling but keep the Lightbox styles separate? Or, even better, in my view, the edit button should even come without any styles from the module, only the lightbox should. Because the edit buttons reside in a design, the lightbox gets added, is kind of like the backend. The edit button as a link is enough – if someone want's to style it, okay, but lets leave this to the author. IMHO this is the process-wire way. Style whats necessary but leave everything frontend related to the author. What do you think? Great module BTW, I like it alot!1 point
-
Hi @sebr , there you go... Note : All the other tasks have as destination wwwroot/assets/dist then the hash task grab the files in this folder and have as destination wwwroot/site/templates/assets/dist then the two tasks below use and rename files in wwwroot/site/templates/assets/dist and update the _main.tpl file : My dir tree : wwwroot --- assets ------ bower_components ------ node_modules ------ dist ------ css ------ js ------ ... ------ gulpfile.js ------ bower.json ------ package.json --- site ------ templates --------- views ------------ _main.tpl --------- assets ------------ dist ------------ controller1.php ------------ controller2.php ------------ ... --- wire --- index.php --- ... // require var path = require('path'); var fs = require('fs'); var gulp = require('gulp'), hash = require('gulp-hash-filename'), replace = require('gulp-replace'), foreach = require('gulp-foreach'); //tasks gulp.task('hash', function() { return gulp.src(['dist/*']) .pipe(hash({ "format": "{name}.{hash}.{size}{ext}" })) .pipe(gulp.dest('../site/templates/assets/dist')); }); gulp.task('main-tpl-css', function() { return gulp.src('../site/templates/assets/dist/*.css') .pipe(foreach((stream, file) => { var id = basename(file.path).split('.'); var regexp = new RegExp("\\echo \"<link id='"+id[1]+"' rel='stylesheet'.*", "g"); return gulp.src('../site/templates/views/_main.tpl', { base: './' }) .pipe(replace(regexp, "echo \"<link id='"+ id[1] +"' rel='stylesheet' type='text/css' href='{$assets_url}dist/" + basename(file.path) + ".css'/>\";")) .pipe(gulp.dest('./')) })) }); gulp.task('main-tpl-js', function() { return gulp.src('../site/templates/assets/dist/*.js') .pipe(foreach((stream, file) => { var id = basename(file.path).split('.'); var regexp = new RegExp('\\<script id=\''+id[1]+'\'.*>', 'g'); return gulp.src('../site/templates/views/_main.tpl', { base: './' }) .pipe(replace(regexp, '<script id=\''+ id[1] +'\' src=\'{$assets_url}dist/'+ basename(file.path) + '.js\'></script>')) .pipe(gulp.dest('./')) })) });1 point
-
https://www.baumrock.com/portfolio/hrdiamonds-360-feedback-tool/ This tool was developed for the vienna based HR company hrdiamonds.com. They can create projects for their clients, setup the feedback architecture, choose from a library of competences and create their very own surveys and provide highly customized services for their clients. Highlights: Everything multilingual (EN/DE) PDF reports with custom designs, table of contents, page numbers, importable custom pdfs (annex, written in MS Word, so they have perfect freedom and ease of use) and of course: pretty charts (done by chart.js): Scalable and nice UI by RockGrid+batcher in several custom process modules: Automatic multilingual e-mails with several variables: Another example of RockGrid: Customizable groupings of feedback-roles (there have to be at least 3 feedbacks per role so they need to have the possibility of aggregating different feedbacks-roles). This project was online for some time already but I ported it from RockDatatables to RockGrid which I plan to release in the next days. If anybody is interested in using/reselling this tool feel free to contact me via PM ?1 point
-
Over the years, I accumulated so many custom API scripts, that I have decided at some point to simply include a special template in my PW boilerplate that holds all these utility / "batch-operation" API scripts in one place. In the template settings, I allow URL segments, and make sure access is for superusers only. This "API-scripts" template has (for better maintainability / readability) a simple switch/case that loads a certain .php file via include: So, if e.g. I need a quick listing / overview of all fields that a certain template has, I go to: mysite.com/api-scripts/fields - then I go back and lock the template again = comment the first few lines for security reasons (one can never be too paranoid...). For me, these are big time-savers, because even if you have to modify the included scripts for the current project, at least I don't have to search for these scripts over and over again and guess "where have I been using something similar the last time?" tl;dr: It's like having the whole PW-recipes site (and more) always at your fingertips ?1 point
-
server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name example.com; root /home/forge/example.com/public; index index.html index.htm index.php; charset utf-8; # ----------------------------------------------------------------------------------------------- # Access Restrictions: Protect ProcessWire system files # ----------------------------------------------------------------------------------------------- # Block access to ProcessWire system files location ~ \.(inc|info|module|sh|sql)$ { deny all; } # Block access to any file or directory that begins with a period location ~ /\. { deny all; } # Block access to protected assets directories location ~ ^/(site|site-[^/]+)/assets/(cache|logs|backups|sessions|config|install|tmp)($|/.*$) { deny all; } # Block acceess to the /site/install/ directory location ~ ^/(site|site-[^/]+)/install($|/.*$) { deny all; } # Block dirs in /site/assets/ dirs that start with a hyphen location ~ ^/(site|site-[^/]+)/assets.*/-.+/.* { deny all; } # Block access to /wire/config.php, /site/config.php, /site/config-dev.php, and /wire/index.config.php location ~ ^/(wire|site|site-[^/]+)/(config|index\.config|config-dev)\.php$ { deny all; } # Block access to any PHP-based files in /templates-admin/ location ~ ^/(wire|site|site-[^/]+)/templates-admin($|/|/.*\.(php|html?|tpl|inc))$ { deny all; } # Block access to any PHP or markup files in /site/templates/ location ~ ^/(site|site-[^/]+)/templates($|/|/.*\.(php|html?|tpl|inc))$ { deny all; } # Block access to any PHP files in /site/assets/ location ~ ^/(site|site-[^/]+)/assets($|/|/.*\.php)$ { deny all; } # Block access to any PHP files in core or core module directories location ~ ^/wire/(core|modules)/.*\.(php|inc|tpl|module)$ { deny all; } # Block access to any PHP files in /site/modules/ location ~ ^/(site|site-[^/]+)/modules/.*\.(php|inc|tpl|module)$ { deny all; } # Block access to any software identifying txt files location ~ ^/(COPYRIGHT|INSTALL|README|htaccess)\.(txt|md)$ { deny all; } # Block all http access to the default/uninstalled site-default directory location ~ ^/site-default/ { deny all; } #Amplify dashboard location /nginx_status { stub_status on; allow 127.0.0.1; deny all; } # ----------------------------------------------------------------------------------------------- # If the request is for a static file, then set expires header and disable logging. # Give control to ProcessWire if the requested file or directory is non-existing. # ----------------------------------------------------------------------------------------------- location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|eot|woff|ttf)$ { expires 15d; log_not_found off; access_log off; try_files $uri $uri/ /index.php?it=$uri&$query_string; } # ----------------------------------------------------------------------------------------------- # ProCache Rules # ----------------------------------------------------------------------------------------------- set $cache_uri $request_uri; if ($request_method = POST) { set $cache_uri 'nocache'; } if ($http_cookie ~* "wires_challenge") { set $cache_uri 'nocache'; } if ($http_cookie ~* "persist") { set $cache_uri 'nocache'; } # ----------------------------------------------------------------------------------------------- # This location processes all other requests. If the request is for a file or directory that # physically exists on the server, then load the file. Else give control to ProcessWire. # ----------------------------------------------------------------------------------------------- location / { expires -1; try_files /site/assets/ProCache-b3d534d...d/$cache_uri/index.html $uri $uri/ /index.php?it=$uri&$args; } location = /favicon.ico { access_log off; log_not_found off; } location = /robots.txt { access_log off; log_not_found off; } access_log off; error_log /var/log/nginx/example.com-error.log error; error_page 404 /index.php; location ~ \.php$ { fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass unix:/var/run/php/php7.2-fpm.sock; fastcgi_index index.php; include fastcgi_params; } location ~ /\.ht { deny all; } }1 point
-
I don't think specifically learning jquery is needed anymore. I'd rather try to improve your skills of using plain js, which should result in using jquery being more or less "reading the docs" if you need it. If the foundation in plain javascript is given or you start to have spaghetti code then look into the OOP features of js and frameworks like Vue/React/Angular. Additionally I'd like to add Svelte to the mix as well. It does look quite similar to Vue, but does include less of the features/magic one might not need in Vue. It's api look way more like plain javascript.1 point
-
Update: working with this setup for a few months, I had quite a few permission related issues which were frustrating. So I decided to do some more research on existing docker projects that are well maintained and bring the features I need. Finally I found http://laradock.io/. I've been using it for 3 months now and I am really happy with it. Very flexible and well maintained set of docker containers. I'm totally happy and can recommend it to devs who are interested in this topic.1 point
-
Hey, I've been trying to implement some progressive enhancements to take advantage of modern browsers, modern JS and CSS capabilities etc. One thing I've got stuck is to CSRF protection using $session->CSRF. I'm echoing hidden token using <?= session()->CSRF->renderInput('contact') ?> inside the form, and I can validate the token with plain POST request (without AJAX) just fine using session()->CSRF->hasValidToken('contact'). For AJAX, I'm setting headers x-<tokenname>:<tokenvalue>. It shows up in both Chrome DevTools correctly, and on backend lke HTTP_X_<TOKENNAME> => <TOKEN_VALUE> as expected, so there's no miscommunication. But, when I try to validate it, it fails no matter what. After some debugging I realized at each request, a new token is created, which invalidates the one I'm sending. Here are the relevant parts from the core. Inside /wire/core/SessionCSRF.php, where validation occurs <?php public function hasValidToken($id = '') { $tokenName = $this->getTokenName($id); $tokenValue = $this->getTokenValue($id); // ... if($this->config->ajax && isset($_SERVER["HTTP_X_$tokenName"]) && $_SERVER["HTTP_X_$tokenName"] === $tokenValue) return true; if($this->input->post($tokenName) === $tokenValue) return true; // if this point is reached, token was invalid return false; } it gets token name from here where it checks inside $_SESSION variable <?php public function getTokenName($id = '') { $tokenName = $this->session->get($this, "name$id"); // Why can't it find token inside $_SESSION global? if(!$tokenName) { $tokenName = 'TOKEN' . mt_rand() . "X" . time(); // token name always ends with timestamp $this->session->set($this, "name$id", $tokenName); } return $tokenName; } I dont understand why it cannot find correct token and regenerates? Does session not last until browser closes? I can save other data to $session, and get it just fine, am I missing something?1 point
-
Looking at the requirements i think these privileges should be enough? Data: SELECT, INSERT, UPDATE, DELETE Definition: CREATE, ALTER, DROP Extra: INDEX Similar to this requirement from Wordpress... http://wordpress.stackexchange.com/questions/6424/mysql-database-user-which-privileges-are-needed Also points out a nice config conditional trick where by a higher privileged DB user is used in the admin area, and normal pages use lower privileges (possibly just SELECT). Hope this helps keep ProcessWire setups even more secure.1 point
-
Thanks Kondogo, I found a good example in the forum on how to use it: https://processwire....-line-wiretabs/ $form = $this->modules->get('InputfieldForm'); $this->modules->get('JqueryWireTabs'); foreach(array('One', 'Two', 'Three') as $number) { $tab = new InputfieldWrapper(); $tab->attr('id', 'tab_' . $number); $tab->attr('title', $number); $tab->attr('class', 'WireTab'); $markup = $this->modules->get('InputfieldMarkup'); $markup->label = $this->_('Label ') . ' ' . $number; $markup->value = "<h2>$number</h2>"; $tab->append($markup); $form->append($tab); } echo $form->render(); The only thing is it creates accordions instead of tabs, but when I work out the details of getting tabs ill post the solution. Thx.1 point
-
I like this solution: $events1 = $pages->find("template=event, date>=today"); $events2 = $pages->find("template=event, date<=today, date_end>=today"); $events = $pages->find("id=$events1|$events2, sort=date, limit=15"); // now you can paginate $events1 point
-
WillyC is right! How could I missed it So you can do: $form->setMarkup(array( 'list' => "<div {attrs}>{out}</div>", 'item' => "<div {attrs}>{out}</div>" ));1 point
-
[quotamos]This is really interesting stuff and I'm learning so much from it. I've already tested Soma's code and it works very well. Is there a way of configuring $form->render() so that it outputs different html (divs for ul/li etc.)? [/quotamos] you.can usage. $form->setMarkup(); und $form->setClasses(); two.set markups und html caresses. see.eliamos /wire/core/InputfieldWrapper.php1 point