Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 02/25/2020 in all areas

  1. Why not just mount the volume as site/assets/files and copy the existing folders there?
    3 points
  2. Hi Orkun! I use the Firebase PHP JWT library when I need to use JWTs, and I would do it like this with PW: use \Firebase\JWT\JWT; // http://example.com/sso/?token=eyJhbGciOiJIUzI... $token = wire('input')->get('token'); // If not token, show error? $key = 'ABC123'; // Store/load your key somewhere (e.g. PW's $config var) try { $decoded = JWT::decode($token, $key, array('HS256')); } catch (\Exception $e) { // Error parsing/decoding token - do not accept. Show error/redirect. } // print_r($decoded); // Find user based on supplied email. // Use other PW user fields or properties from JWT as necessary. $u = wire('users')->get('email=' . wire('sanitizer')->selectorValue($decoded->email)); if ( ! $u->id) { // Could not find user - don't exist. // Could create them at this point, if you have enough detail in the JWT to do so. } // Force user login wire('session')->forceLogin($u); // Go to another page (don't stay on this one) wire('session')->redirect('/');
    2 points
  3. Plenty of posts on the forum relating to Content Security Policy (CSP) and how to integrate it with Processwire. It's not too hard to implement a decent htaccess CSP that will get you a solid B+ at Mozilla Observatory. If you're after A+ it's a little harder because of all the back-end stuff... until you realize it's surprisingly easy. After a lot of testing, the easiest way I found was to specify only what is needed in the htaccess and then add your required CSP as a meta in your page template. Plenty of people have suggested similar. Works very easily for back-end vs front-end, but gets complicated if you want front page editing. Luckily, a little php will preserve back-end and front page editing capabilities while allowing you to lock down the site for anyone not logged in. None of this is rocket science, but CSPs are a bit of a pain the rear, so the easier the better, I reckon ? The only CSP I'd suggest you include in your site htaccess is: Header set Content-Security-Policy "frame-ancestors 'self'" The reason for this is you can't set "frame-ancestors" via meta tags. In addition, you can only make your CSP more restrictive using meta tags, not less, so leaving the back-end free is a solid plan to avoid frustration. Then in your public front-facing page template/s, add your desired Content Security Policy as a meta tag. Please note: your CSP should be the first meta tag after your <head>. For example: <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Security-Policy" content="Your CSP goes here"> <!-- followed by whatever your normal meta tags are --> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="format-detection" content="telephone=no"> If you haven't got Front Page Editing enabled, this works fine by itself. Just one extra step is needed to make sure you don't have to worry either way. The easiest way I found to allow both CSP and front page editing capabilities is the addition of a little php, according to whatever your needs are. Basically, if the user is a guest, throw in your CSP, if they're not do nothing. It's so simple I could have kicked myself when it finally dawned on me. I wish it had clicked for me earlier in my testing, but it didn't so I'm here to try to save some other person a little time. Example: <!DOCTYPE html> <html> <head> <?php if ($user->isGuest()): ?> <meta http-equiv="Content-Security-Policy" content="Your CSP goes here"> <?php endif; ?> <!-- followed by whatever your normal meta tags are --> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="format-detection" content="telephone=no"> If you want it a bit more involved then you can add additional tests and be as specific as you like about what pages should get which CSP. For example, the following is what I use to expand the scope of the CSP only for my "map" page: <?php $loadMap = $page->name === "map"; ?> <!DOCTYPE html> <html> <head> <?php if ($user->isGuest()): ?> <meta http-equiv="Content-Security-Policy" content="default-src 'none'; base-uri 'self'; manifest-src 'self'; form-action 'self'; font-src 'self' data: https://fonts.gstatic.com; frame-src 'self' https://www.youtube.com; img-src 'self' data:<?php echo ($loadMap) ? " https://maps.googleapis.com https://maps.gstatic.com" : ""; ?> https://www.google-analytics.com; script-src 'self' <?php echo ($loadMap) ? "https://maps.googleapis.com " : ""; ?>https://www.google-analytics.com https://www.googletagmanager.com; style-src 'self' <?php echo ($loadMap) ? "'unsafe-inline' https://fonts.googleapis.com" : ""; ?>"> <?php endif; ?> Hope this saves someone a little time testing. https://observatory.mozilla.org/analyze/bene.net.au
    1 point
  4. This is an update about how it's been running blog sites using ProcessWire. I hope it's OK for me to post in this category even though I've already showcased my sites awhile back. I thought it would be helpful for people to get a feel for what it's like to use ProcessWire on an ongoing basis for blogging. Often people talk about the development of a site, but it's not quite as often that we hear about the ongoing running of a PW site and how the PW API influences that, which is what I'll cover here. As background, we at The GrayFly Group own and run the blogs goodkidsclothes.com and flipfall.com. The development of these PW sites has been covered in a showcase thread for GoodKidsClothes and another for FlipFall. Here are some of the unique experiences I've had running these two sites. "Running" covers everything from coding and making modifications to the templates, to writing our articles, to interacting with ad partners or with others seeking us out for something related to one of those sites. So this is a different experience from agencies who develop for others; we develop for ourselves. As background, the main traffic to the websites comes from organic search results. Income from sites is from affiliate marketing and advertisements. GoodKidsClothes PW experience: "to think it is to do it." For GoodKidsClothes.com, one of the things we noticed was that if we could think it, we could do it, thanks to the easy-to-use PW API. The need for a change Here is a concrete example of what I mean: we noticed that many people would enter the site on an older article (e.g. via a search result). However, we continually put out a lot of time-sensitive information, e.g. a style guide, a piece of news relating to a change in a children's clothing company, etc. I didn't want people to miss out on this, yet many were, because after reading their entry page, they'd leave. They had no idea (unless they clicked on the link to home page) that there was another article that could be of value to them. All too often, by the time people learned about that new article via search results, they'd be too late for the news to be relevant - in fact, it wouldn't even be the newest article anymore by that point. The solution So, using the PW API, we modified the article template so that if someone was reading any article that was not the most recent article, then at the end of what they're reading, they'd see a small section highlighting the most recent article. Here is a screenshot: As you can see above, our newest article is highlighted immediately below the article they're reading, unless of course they are already reading the newest article. In the case shown above, the newest article (recipe-related) did not happen to be time-sensitive, but in most cases that article would be time-sensitive, so that's why we made this change. To make the change we simply used the PW API to query what the latest article was and store its identity in a variable - those sorts of queries we set up in _init.php. Then we modified the article template such that if the current page was not the latest article, to include the featured box that you see above. Another need for a change You'll also notice links in boxes above and below where the featured article box is. These are ads (they blend OK right?!) These ads brought another problem to our attention: we'd put the ads blocks on all articles equally. However, in the case of the most recent article, often the most recent article would usually have a time-sensitive offer or some other call to action e.g. signing up for our newsletter (well, not in the case of the recipe article above, but in most cases the latest article would have something we prefer the reader to do). We didn't then want our readers to get distracted by the ads and either leave the site, or click on an ad and click away from the site, instead of doing whatever the call to action is. The solution Again using the ProcessWire API, we modified the "article" template so that there was conditional logic on the ads: if the current page is not the latest article, include the ad code (otherwise no ads). This mean no ads were seen on the most recent article, allowing for less distractions to the reader on time-sensitive articles and more likelihood of them following through on the call to action. Conclusion for GoodKidsClothes We were able to make all these changes within minutes of thinking of them! In-house, without a ton of knowledge of programming, thanks to the awesome ProcessWire API. We actually made all those changes live, i.e. going in there and making changes to the code of the site as its running live. Yes, we had backups of the entire site and we always first save a copy of the template file under a different name (usually prefixing it with OLD_ ) before modifying the live version. This is how helpful ProcessWire is. We can make changes that benefit our site and make them in-house as we think of them. If this was done under some other CMS, we would be unable to make those changes without either a) hiring a developer or b) training up in whatever the other CMS is to make the changes in-house. Either way, it would take considerably more time to do anything. So, despite not having a formal programming background, we now have a very "nimble" site that we can adapt as needed to changes that we desire, within minutes of thinking of the change we need, with only needing to know a little PHP, html, and CSS, just the very basics, and looking up the PW API. FlipFall PW experience: "the answer is yes." In the case of FlipFall, there have been times when a potential ad partner asks a question like "can you put different ads on different categories?" or other things. Sometimes they are questions I ask myself of the website "Can we do A/B testing of different ads; i.e. show a certain ad block 50% of the time totally randomly and another ad block the other 50% of the time?" "How about ads from this company some of the time and a different company other times?" The answer is always "yes." Coming from other CMS's (that I used but did not program with) I used to brace myself a bit if I saw an email that asked "Can you....?" but now thanks to ProcessWire I don't have that bracing reaction any more. So long as I can think of a way to do it (and so far I always have, thanks to the PW API), I can say "Yes we can." More to the point, I can actually say "Yes, we can make those changes in-house within [whatever brief timeframe I think it will be]" instead of having to be vague about timeframes because of needing a developer. So I no longer worry about "Can you ...?" questions because the answer is yes. Overall conclusions ProcessWire is a superb CMS for those who own and run a site. The PW API makes it easy to make changes to the look and functionality of the site as needed. Such modifications wouldn't easily be possible on alternative CMS's that are heavily "theme-based".
    1 point
  5. @bernhard - I've added that link to the keyboard shortcuts dialog in the latest version. I've also added that dialog to the FileEditor panel.
    1 point
  6. Thanks for the link @bernhard but I think this is the one that I should probably link to: https://github.com/ajaxorg/ace/wiki/Default-Keyboard-Shortcuts
    1 point
  7. If you are using the separate ModuleConfig class method you can use it like this: // Get module config. // (Holds merged data from DB and default config. // This works because of using the ModuleConfig class) $moduleConfig = $this->wire('modules')->get('ModuleName'); // You can than access the keys like this: $value = $moduleConfig->name_of_key;
    1 point
  8. If you are using the separate ModuleConfig class method you can use it like this: // Get module config. // (Holds merged data from DB and default config. // This works because of using the ModuleConfig class) $moduleConfig = $this->wire('modules')->get('ModuleName'); // You can than access the keys like this: $value = $moduleConfig->name_of_key;
    1 point
  9. From my linked post: https://processwire.com/talk/topic/17346-hook-on-repeater-field-save/?do=findComment&comment=152504 ProcessWire has a feature to track changes. If there are no changes unneeded hooks do not get fired. This is not only better for performance (I guess) but also great for conditional hooks: https://processwire.com/blog/posts/new-ajax-driven-inputs-conditional-hooks-template-family-settings-and-more/#new-conditional-hooks
    1 point
  10. 1 point
  11. Thanks @Robin S! There can be more than 100 result, so I think I will go with the SQL then. If I manage to make any progress, I will post some code here in case anyone else needs it.
    1 point
  12. There's no magic option - you have to code your own search in the way that suits you. If the number of search results is not huge and pagination is not required then you can get all the results where any field matches, and then divide off the pages that have matches in the title field, rendering those results before the others. Otherwise you might want to use an SQL query, perhaps returning just an array of page IDs which you could then slice according to the pagination number and load to a PageArray via $pages->getById().
    1 point
  13. Hi @Bacelo, I'm an artist who just coded his own website with PW. I basically learned enough PW and php to code it in the past 1.5 months. This is before I started learning about SEO...so I've been thinking about the right site construction. I might have to amend my menu links etc. I've been testing an SEO program and they linked to a number of publicly available articles. This one I think is the best. https://moz.com/blog/site-architecture-for-seo. The main takeaway from this article is that the site architecture should be as flat as possible. So keeping in mind that I'm a beginner in php and pw and all things programming: I may be misunderstanding your description, but why is a painting in two categories? Would there be an issue of duplicate content? Maybe you can solve this with the canonical link then? I like that a painting=page. That's the way I did mine as well (I'm a photographer). Image = page. I don't use the multi image field anywhere in the site (e.g. in a blog post). In learning about SEO, text is very important, will there be blog posts? In the previous website incarnations, my site had images with only title and caption, which google considered to be thin content. How is the client going to solve that? I'm still trying to solve this for myself. For now, what I've done is that when I talk about a certain image in a blog post, I will purposefully link to the image page from the blog_body. In the image page, i have Related Writing code that automatically picks up any page that links to it using pagelinks(). I think over time this will work well if I want to stay with image=page. I'm going through my past blog posts to link them over time. An alternative I've considered is not to have individual image pages (to avoid the thin content). Instead I would only have a gallery page with say all the images lazy loaded as you describe. If a user wants to see a larger version, then they click on it, and a larger version pops up (I forget the module that does this, but there's several). I ended up not doing this because I want each image to have more information displayed over time like edition, exhibition history, buy button, etc, and based on my reading of the module, you can't fit that into a pop-up (whatever you call those things). As stated the main takeaway I think is to have a flat structure for search engines while making it as pleasant for user experience. Regards,
    1 point
  14. Hi @Mike Rockett - not sure what you think about this idea, but I recently came across a situation where I think it would be helpful if Jumplinks was loaded before the core PagePathHistory module. PPH has set up and automatic redirect on a page, but I hav a more detailed set of rules set up in JL that handles urlsegments using {all}. The problem is that PPH is loading first so the JL rules were being ignored. In this case I decided to manually remove the PPH rules from its DB table, but I think that possible just setting the JL autoload priority setting might also work just fine. Do you think this would make sense in all cases?
    1 point
  15. I believe the problem is when the pages are stored under the admin branch it will apply admin permissions. I think you have use include=all in your find?
    1 point
  16. So you need "secured-files-dir" directory on the same level as your site root: - www -- your-site-root -- secured-files-dir
    1 point
  17. U need absolute/relative filepath but not url. Ex: /var/www/secure/ or c:\www\secure or something like ./../secure if U use windows local server and linux production server
    1 point
  18. Also think getting it at least installable with composer, if not packaged as phar file would help for now.
    1 point
  19. Thanks! Anyone interesting in taking this project over? Given tools like this are part and parcel of a good developer experience these days I feel it is important to keep this project active to attract new devs. I would happily contrib to setting up new docs. Just been mucking around with vuepress, makes docs a cinch.
    1 point
  20. This is what I came up with today: I have a main module that installs 3 other modules (via module info "installs" => ["mod1", "mod2", "mod3"]). Uninstall was a bit of a problem, because it tried to uninstall a fieldtype module and this was not possible when I had an existing field of that type. Throwing an exception did also not work, because all submodules where uninstalled even if the main module threw an exception. I then tried to throw an exception in all of the submodules as well, but that was a mess and did not work reliably. Hooks to the rescue: public function init() { $this->addHookBefore("Modules::uninstall", $this, "customUninstall"); } /** * Custom uninstall routine * * @param HookEvent $event */ public function customUninstall($event) { $class = $event->arguments(0); if($class != 'yourmodulename') return; // set flag $abort = false; // check1 if($this->check1() == false) { $this->error('check1 failed'); $abort = true; } // check2 if($this->check2() == false) { $this->error('check2 failed'); $abort = true; } // uninstall? if($abort) { // there where some errors $event->replace = true; // prevents original uninstall $this->session->redirect("./edit?name=$class"); // prevent "module uninstalled" message } } Real life example that also checks if the uninstalled module is the main module or a sub-module. If it is a sub-module it shows an error and redirects to the config screen of the main module: public function init() { $this->addHookBefore("Modules::uninstall", $this, "customUninstall"); } /** * Custom uninstall routine * * @param HookEvent $event */ public function customUninstall($event) { $installs = $this->getModuleInfo(); $class = $event->arguments(0); $url = "./edit?name=$class"; // exit when class does not match if(!in_array($class, $installs)) return; // intercept uninstall $abort = false; // if it is not the main module we redirect to the main module's config if($class != 'RockMarkup') { $abort = true; $url = "./edit?name=RockMarkup"; $this->error('Please uninstall the main module'); } // check if any fields exist $fields = $this->wire->fields->find('type=FieldtypeRockMarkup')->count(); if($fields > 0) { $this->error('Remove all fields of type RockMarkup before uninstall!'); $abort = true; } // on uninstall of the main module we remove this hook so that it does // not interfere with the auto-uninstall submodules if($class == 'RockMarkup') $event->removeHook(null); // uninstall? if($abort) { // there where some errors $event->replace = true; // prevents original uninstall $this->session->redirect($url); // prevent "module uninstalled" message } }
    1 point
  21. $this->addHookAfter("ProcessPageEdit::buildForm", function (HookEvent $event) { $page = $event->object->getPage(); if ($page->template->id == 89 && $page->parent->parent->id == 11180) { $repeater = $page->pro_table; $itemCount = $repeater->count(); $c = 1; $grandTotal = 0; foreach ($repeater as $rep) { if($c < $itemCount ) { $num_days = (float) $rep->days; $day_rate = (float) $rep->day_rate; $row_total = $num_days * $day_rate; $rep->row_total = $row_total; $grandTotal = $grandTotal + $row_total; $page->save(); unset($num_days); unset($day_rate); unset($row_total); } if ($c === ($itemCount)) { $rep->row_total = $grandTotal; $page->save(); } $c++; } } }); OK, got it now. Used another hook. Works like a charm.
    1 point
  22. It's Bootstrap-specific in that Bootstrap requires you to add (among many, many other things) an unnecessary data-toggle="dropdown" attribute to the <a> element. It's unnecessary as that element can already be targeted as a direct child of an <li> element with "has_children" class (or whatever other class you might want to use for dropdown menu purposes). That is what @ottogal referred to above: MarkupSimpleNavigation does not equal ProcessWire - it's a third-party module for ProcessWire. PW allows you to generate your markup any way you choose. Personally I find MSN to be a very useful module but it's not compulsory to use it. Some people create their own menu markup from scratch using just the API and basic PHP functions like foreach(). And there are other modules for generating menu markup such as Menu Builder (haven't used it myself). I'm not a good one to answer this as I don't like CSS frameworks - I find them a hindrance rather than a help. I prefer to create my stylesheets for each project from scratch using SCSS. That way there's no bloat and I can build exactly to my design mockups without needing to conform to any framework expectations. I understand UIKit is popular with others though.
    1 point
×
×
  • Create New...