Leaderboard
Popular Content
Showing content with the highest reputation on 10/31/2018 in all areas
-
We have relaunched the old website of design business expert Joachim Kobuss. The old site desperataly needed a facelift and a streamlined CMS that allowed our client to fill over 130 pages of content in a span of two weeks. We at schwarzdesign used ProcessWire + ProFields for the Backend and built a Bootstrap 4.1-based frontend. Features / Services provided Responsive design featuring a desktop layout with two fixed navigation areas and a fixed sidebar that form a frame around the content. Carefully set typography and spacing for a smooth reading experience for long texts on all devices. A hierarchical page tree with three levels of nested pages, all using the same simple set of fields. Password protection for individual pages and an optional password request form. Privacy by design: There's no tracking, no Google Map, no Facebook Like Button or anything like that on the page. Because we don't set any cookies or include third-party code, we don't need a cookie notice ? Modules used Profields (especially Repeater Matrix, Textareas and Functional Fields) Form Builder Tracy Debugger Wire Mail SMTP Duplicator Admin Links in Frontend Sitemap Optimizing for content The most distinguishing feature is the large amount of long texts our client has written. So it was important to provide a good editing experience in the frontend and have a content centered design that made long text sections easy to follow. We didn't want to give our client just a large CK Editor body text, since in our experience, those WYSIWYG editors aren't actually that easy to use for non-technical folk. It also reduces the amount of control we as designers and CSS-authors have over the presentation of the content. So instead, we built a flexible section system using the Repeater Matrix field of the ProFields module. There are three sections: text content, downloads and single image. Each section has a headline field and a radio selection field to switch between two levels of headline hierarchy (corresponding to h2 and h3). For the text section, there's a CK Editor textarea stripped to the bare minimum (strong, italic, lists, blockquotes and links), with no confusing styles or format dropdown. The image section features an additional option for full- or half-width images and an option to display the image description as a caption. And of course, the download section has a multivalue file field that is displayed as download buttons in the frontend. This simple sectioning system allowed us to build the entire site (except for the homepage) using just one template fieldset. There are three templates: Basic Page, Topic and Article. Basic pages are for generic pages like imprint and data policy. Topics may only be children of the homepage, while articles may be children of a topic or of another article, so the pages can be nested indefinitely. This provides the hierarchical structure used for the page layout. Topic and article inherit the fieldset of the basic page, so it's just one template under the hood. There's also smart Open Graph tag generation; title, description and preview image are automatically generated based on the first suitable sections on each page and can be manually overridden using the SEO tab available on all pages. Laying out the page Our design has three fixed areas: The top navigation, the left side navigation and the right sidebar, which shows some general contact info and a random image. The top navigation always shows the top-level topic pages, the sidebar navigation contains all articles in the current topic, displayed in a hierarchical structure. This was technically challenging, as the many fixed layout areas broke the normal pageflow and didn't work well for smaller devices. I solved this using four seperate Bootstrap containers, three of which are fixed. Only the container with the main page content flows normally. The left sidebar only fills the three leftmost columns of its container, the right sidebar the three rightmost columns, and the main content takes up the six center columns of it's container. All three have an offset to the top to make space for the fixed header navigation. This way, all the seperate layout areas can never overlap. The CSS that applies position: fixed to the containers is wrapped in a media query with a min-width, so on tablets and mobile devices, the areas simply stack. Check out the source code to see how those containers are laid out! The logo is text by the way, not an image. It's positioned using CSS3 transforms. Password protection Our client wanted to password protect some of his pages with varying passwords, so he can give different people access to different sets of pages. Also, he wanted to have a password request form, where people can submit their name and contact information to request access to a specific page. In the backend, we added a password field that activates the password protection for that page. There's also a checkbox to display the password request form. The form is built using the Form Builder module (and a simple hook to add the current page title to the outgoing mail). However, for the password protection, we built a custom solution. While there is a readymade module available, we didn't want something based on user accounts. A visitor should be able to simply input the password on a protected page and start reading, without bothering with registering an account. The authentification is stored in the session, so after closing the browser you have to input the password again, but that seemed to be a worthy tradeoff. Anyway, when visiting a password protected page, the template checks if the user is already authentificated to read this page; if so, it displays the page content, otherwise it displays the password input form and the password request form if it was also activated in the CMS. A nice-to-have feature that we built in addition is that if multiple pages use the same password and you input it on one of them, you are automatically authentificated to view all of them during the current session. A caveat of this method is that since the page content depends on the current session, we couldn't use the inbuilt page cache at all. So instead we used the cache API to cache rendered section markup and the navigation menues, which still results in a blazingly fast site. For the techies amongst you, here's the PasswordProtectedPage class we wrote for this functionality: <?php namespace schwarzdesign; use Processwire\Wire; use Processwire\Page; use Processwire\PageArray; use Processwire\User; class PasswordProtectedPage extends Wire { const PASSWORD_FIELD = 'page_password'; const PASSWORD_INPUT_NAME = 'page_password'; const STORAGE_KEY = 'authentificatedPages'; const STATUS_FREE_ACCESS = 'free_access'; const STATUS_AUTHENTIFICATED = 'authentificated'; const STATUS_NOT_AUTHENTIFICATED = 'not_authentificated_yet'; const STATUS_WRONG_PASSWORD = 'wrong_password'; /** * The status of the authentification. */ public $status = self::STATUS_NOT_AUTHENTIFICATED; private $page; private $authentificated_pages = []; public function __construct(Page $page) { $this->page = $page; $this->authentificated_pages = $this->getAuthentificatedPagesFromStorage(); } public function handleRequest() { // pages with no password set if (empty($this->page->get(self::PASSWORD_FIELD))) { return $this->status = self::STATUS_FREE_ACCESS; } // pages that the user is already authentificated to use if (in_array($this->page->id, $this->authentificated_pages)) { return $this->status = self::STATUS_AUTHENTIFICATED; } // if the user set the input, check the password if ($password = $this->getInputPassword()) { if ($this->passwordIsCorrect($password)) { $this->authentificatePagesByPassword($password); $this->storeAuthentificatedPages(); return $this->status = self::STATUS_AUTHENTIFICATED; } else { return $this->status = self::STATUS_WRONG_PASSWORD; } } else { return $this->status = self::STATUS_NOT_AUTHENTIFICATED; } } public function userCanAccess() { return in_array($this->status, [self::STATUS_AUTHENTIFICATED, self::STATUS_FREE_ACCESS]); } public function getInputPassword() { $password = $this->wire('input')->post(self::PASSWORD_INPUT_NAME); if (empty($password)) { return null; } return $password; } public function authentificatePagesByPassword(string $password) { $pages = $this->wire('pages')->find(self::PASSWORD_FIELD . '=' . $password); $ids = array_map(array($this, 'extractIdFromPage'), iterator_to_array($pages)); $this->addAuthentificatedPages($ids); } /** * Private helper Functions. */ private function passwordIsCorrect(string $password) { return (string) $this->page->get(self::PASSWORD_FIELD) === $password; } private function extractIdFromPage(Page $page) { return $page->id; } private function addAuthentificatedPages(array $page_ids) { $this->authentificated_pages = array_merge($this->authentificated_pages, $page_ids); } private function getAuthentificatedPagesFromStorage() { $ids = $this->wire('session')->get(self::STORAGE_KEY); return $ids ? $ids : []; } private function storeAuthentificatedPages() { $this->wire('session')->set(self::STORAGE_KEY, $this->authentificated_pages); } } This is used in the template like this: <?php namespace Processwire; use schwarzdesign\PasswordProtectedPage; $protectedPage = new PasswordProtectedPage($page); $protectedPage->handleRequest(); if (!$protectedPage->userCanAccess()) { if ($user->hasPermission('display-page-password')) { /* Display the password in plaintext for editors & admins */ } /* Display the password input form */ if ($page->show_password_request_form) { /* Display the password request form */ } } else { /* Display the page content */ } Screenshots13 points
-
4 points
-
That video got me hooked as well. I'd love to help out with making a new marketing video. I can do the screen recording, video editing and voice-over. If someone can concept out a script/storyboard, I can take care of the rest. Maybe it can be featured on the new PW homepage hero section to hook more people.4 points
-
Thanks, I just tried it out on my local dev copy and they've not improved on any of the flaws. You still can't set more than one answer as the best You can't reply to answers (like StackExchange does) so there can be no discussion as upvotes/downvotes break the flow You can't mix and match QA topics and normal topics in the same forum (less of an issue for a Getting Support forum) Any of the sorting (by date or votes) is per-member and not set in the admin So the big problem is it breaks the discussion flow completely still. I'll have a poke around and see if there are any third-party modules that might do what we want because this is still very incomplete in terms of features unfortunately.3 points
-
Not sure if that's the best approach ? With page reference fields I think you want to go with a custom selector and add "check_access=0" to the selector.3 points
-
There is a hacky way around this. This comes direct from the ready.php file from one of my sites - in this case it's for the autocomplete inputfield, but maybe something like this would be useful for you also? // hack to overcome this: https://github.com/processwire/processwire-issues/issues/550 $this->addHookBefore('Pages::find', function(HookEvent $event) { $selector = $event->arguments(0); if(is_string($selector) && strpos($selector, 'template=user') !== false && strpos($selector, 'name|first_name|last_name%=') !== false) { $selector .= ', check_access=0'; } $event->arguments(0, $selector); });2 points
-
That's easy enough to implement. The only decision I was struggling with is how ?. My original idea (which I have now discarded given the feedback here) was to have customers as normal ProcessWire users. The advantage of that is that we would't need to have the same data stored in two different places; as ProcessWire Users and also as customer data in our Orders field. Using that approach, a simple customer id in Orders field would reference the user. Now we can do it the other way around, maybe incorporating this idea: We were always going to have a 'separate dashboard' for users/customers, albeit, referencing ProcessWire users with a certain role, like 'pad-customer' or similar. I'll write more about this later. Give the previous comments, we can instead have this dashboard backed by its own Field OR external DB table. We already have a Customers Fieldtype. It will just need some tweaking or conversion to a separate db table outside ProcesWire . We'll use the field to store customer data in relation to their orders or abandoned carts, making sure we fulfil our legal obligations (if required). The only tricky bit is if those customers decide to get registered. Maybe it's not a big deal. We'd let ProcessWire handle their normal user stuff, like login and permissions and we handle the rest, i.e. their shop related stuff. In this case though, the customer id (from customers table) will be different from their ProcessWire user id. However, the customer Field would reference the User's ProcessWire ID, so no big deal there. For unregistered customers, their ProcessWire ID would be 0. Alternatively, our order Field could store user/customer data directly but I'd rather have them as separate entities due to various advantages, e.g. being able to send newsletters to your customers, sending them promo/discount info, engaging most loyal customers, etc. Just thinking out loud here, at the very least to see if it makes sense to me when I read this again some hours later ?. Thoughts?2 points
-
Apologies for the late response but I think @szabesz nailed it: Exactly. That's why I liked Apeisa's original idea of storing the customer data on the order as well. This way you can easily delete the user and its data except for the data necesseray by law like orders.2 points
-
Then you are going to love the next progress update :-). ?2 points
-
That's a tick then ?. It's already implemented ?!2 points
-
You can just copy over all the files (not a site profile) and make a DB dump and install everything 1:1 on your dev server. Or you can try to use https://modules.processwire.com/modules/duplicator/ No idea what is going on in your case ?2 points
-
Hello Winnie, Welcome to the forums. Depending on your background (i.e. are you a designer, front-end developer, back-end developer, content/marketing person or a unicorn?) there are different paths to take. If I suggest you work yourself through the beginner tutorials of ProcessWire. This will give you a better understandig of the inner workings. Also explore the site profiles which comes with installing ProcessWire.2 points
-
Hi all, This is Margaret from the Web Team at the Australian Antarctic Division. As some of you would be aware, a little while ago we chose ProcessWire as our replacement CMS. We've been working on moving one of our smaller sites since that time (before we set our sights on our main site next year), but a month or so ago our attention was diverted to a brand new site that came up - for the SCAR COMNAP 2020 conference. It's a very small site at this stage (2 pages!), but it will grow a little as time goes on. Technically speaking it's very simple, but I just thought I'd post it here because it is our very first live PW site, which is a little bit exciting! ? https://scarcomnap2020.antarctica.gov.au/ Margaret1 point
-
I can't recall atm, but I tried Adminer in the past and something didn't work so I ditched it. Aha. Keenly watching this...?1 point
-
Am going to ditch phpMyAdmin in favour of Adminer. It's a great tool, especially when used in the Adminer Custom theme/plugin bundle: https://github.com/pematon/adminer-custom The JSON preview plugin rules: No problems with refeshing row edit views in Adminer. Was working on my own PW integration but I think @adrian might have something exciting for us all soon... ?1 point
-
PageListSelect is different because it doesn't get pages via Pages::find, but rather gets the children of individual pages if they are listable. This is what I came up with: $wire->addHookAfter('Page::listable', function(HookEvent $event) { $page = $event->object; // Page is listable if it is the Users parent or a user page and the current user has a given role if(($page->id === 29 || $page->template == 'user') && $this->wire()->user->hasRole('editor')) { $event->return = true; } }); $wire->addHookBefore('ProcessPageList::find', function(HookEvent $event) { $selector = $event->arguments(0); $page = $event->arguments(1); // Don't check access if getting children of the Users parent and the current user has a given role if($page->id === 29 && $this->wire()->user->hasRole('editor')) { $event->arguments(0, $selector . ', check_access=0'); } });1 point
-
No. An external table means I avoid creating pages for each customer. That is not going to be possible. Erasing users will not erase the order data. I am not using page fields or similar. The only thing that would happen in such a case is that a user id stored in a customer database would point to a non existing user ?1 point
-
I love debates ? Jokes aside, some simple features would do I think: a button to prefix the topic's title with either [open], [solved], [closed], etc... a button to highlight replies which – a forum users thinks – SOLVE the issue, rather than being "the best". What is "best" anyway? Ask the guys at Apple, they'll tell you what best is... ?1 point
-
You can pass an array of variables as an $options argument to $page->render(). // Render page echo $some_page->render(['animal' => 'cat', 'colour' => 'marmalade']); // In the template file of the rendered page echo "I have a {$options['colour']} {$options['animal']}."; See Ryan's post here for more info on $page->render():1 point
-
1 point
-
Great that you got it sorted ?. Your solution is a bit ironical though since you previously stated this: ...yet your example does not really do anything with the variables sent (except echo it back verbatim) ; Since you've posted this in the forums with the aim of helping other people who may not be well-versed with JavaScript and/or PHP, I feel inclined to point out two things, lest newbies pick up approaches that may not be best practice (some of which may potentially break their sites): ProcessWire has an $input->get() method (and related ones) which has some advantages over using PHP $_GET. There's two problems here: One, you are not sanitizing your $variable and secondly, you are echoing it back directly to the browser as received by the input. As I pointed out earlier, we have $sanitizer->entities() for such uses.1 point
-
This is a self-contained basic example of how to use $config->ajax: Anyone can put this little demo in a template file and it works. Hopefully it helps other people who don't know Javascript or/and PHP well to understand how to work with Ajax in PW. Something like this is all I needed. Getting the variable(s) ($_GET) and doing something with it - in this basic example just echo it - can also be done in a separate php file in your templates folder that you can include after if($config->ajax) Here is a better example - mainly for my own reference...:1 point
-
I agree the current approach isn't great, but is it possible to simply add "/site/assets/MyModule" to the ignore list. Doesn't that achieve what you want? If not, I'd certainly be happy for a regex approach.1 point
-
Exactly my experience. I read a comment from Ryan on another website (Textpattern blog I think) and initially was enthousiastic, but it felt way to developer heavy. Then a few weeks later I gave it another shot and the video instantly hooked me. Based on the other answers here I guess this might be very interesting. It might even be the best marketing idea I heard in a while. Just show the video. No marketing lingo, but the real back-end with a proper front-end. Focussed on the content and the delivery of that particular content on the front-end. Maybe with ProDrafts.1 point
-
I remember you from the other CMS which was not simple compared to ProcessWire :). Send me a PM, would be great to reconnect.1 point
-
Definitely. The plan is to build on and extend the powerful PW/Padloper API but also providing an easy to use and friendly interface with most useful functionalities for a shop within easy reach. Apart from promotion (we can think about that in the future), the rest of your list is tick, tick, tick, tick + more... It's a great project to work on, thanks! ?1 point
-
Hi @kongondo, I've just seen this thread and couldn't be happier. I used Padloper in the past as an early adopter but I always felt it wasn't for the faint hearted. It's great to know that it has a future and I hope v2 will be possible to use without PHP guru skills. I build almost all my sites on ProcessWire and it'd be nice to have the basic features covered by the module itself (promotion, tax, shipping, user accounts, order management etc…). Many of these were up to us to implement and it was prohibiting for front-end people. Best of luck with the project and thank you for your commitment!1 point
-
Really? Does this ring a bell? ..... What about this one?1 point
-
That's exactly why I built it - thanks for improving it further @adrian ? Just a quick tip you might find helpful. It makes the code more readable if you use constants instead of integer variables. You'll get them from intellisense in your IDE so it's also easier to look them up like this than heading over to the docs: @tiefenbacher_bluetomato Greetings from Vienna to Schladming(?) ? Looking forward to the winter ?1 point
-
1 point
-
I'm not sure if I can implement sorting directly in the database for advanced date parts, but you can sort in-memory. $result = $users->find("profile_birth_date.month=$mes"); $result->sort('profile_birth_date.day'); // $result is now sorted1 point
-
If "the rest" is not obvious you have two options: google ask a specific question here in the forum You are complaining that the examples suppose some kind of basic setup... But that's not a bad thing. That's just to have a common basis and to make sure all are talking about the same. If your setup is different, why don't you bring up a new installation and test things out the way several helpful and experienced people here in the forum where trying to explain? Maybe it has a reason why they do it how they do it?! Have you ever TRIED OUT one of the basic AJAX examples around the web? What are you talking about in your basic demo? Does it work? Does it not work? What author var are you talking about? Nobody here knows anything about your setup. You never told about it in detail. If you just started with one of the shipped site profiles everybody would know what you are talking about and what would be going on. Once that is working and you understand how and why you can move on forward to customized setups.1 point
-
I feel a bit stoopid asking this (I'm new around here), but module class files have a .module extension. Which is a bit annoying as it's a .php file and it stuffs up my editor. To save having to remember how to map extensions in Vim is this required?1 point
-
Try adding... au BufRead,BufNewFile *.module set filetype=php at the end of your .vimrc file and re-launch vim.1 point
-
v0.1.11 released. Thanks to a pull request from @adrian, this update wraps the last breadcrumb item in a link to the page tree (like the other breadcrumb items) and also standardises the page tree links so they always include an "open" parameter to load the tree opened to the clicked page. This is a change from the core breadcrumbs, which treats the link on parent breadcrumb item differently. There is discussion on this topic here: https://github.com/processwire/processwire-issues/issues/22 My opinion is that the breadcrumb tree links should be treated consistently, and if you want to go back to the page tree in its last state you can click the ProcessWire logo or "Pages" or "Pages > Tree" in the main admin menus.1 point
-
@Pete I created an online test version of the actual forum, and the user can choose if he wants to sort by date or by votes. So the upvoted answer is not pulled out of context. I did not try to mark one answer as correct yet, will do later. If you want, I can give you the admin account and URL so you can test for yourself. There is an option in the admin to set the default sort order, but as I logged in as a normal user, it seemed to not respect this order and I had to choose "Sort by date" by myself. Maybe I did something wrong. Have to take a look at it.1 point
-
I have just added access rights to TracyDebugger's RequestInfo > Field Code section. It now contains: [ 'type' => 'FieldtypeText', 'flags' => '32800', 'name' => 'my_field_2', 'label' => 'My Field 2 Label', 'collapsed' => '0', 'minlength' => '0', 'maxlength' => '2048', 'showCount' => '0', 'size' => '0', 'tags' => '', 'editRoles' => [ 'editor', ], 'viewRoles' => [ 'author', 'editor', ], 'textformatters' => '', 'showIf' => '', 'themeInputSize' => '', 'themeInputWidth' => '', 'themeOffset' => '', 'themeBorder' => '', 'themeColor' => '', 'themeBlank' => '', 'columnWidth' => '100', 'required' => '', 'requiredAttr' => '', 'requiredIf' => '', 'stripTags' => '', 'placeholder' => '', 'pattern' => '', ] which is everything to need to create a field via the API including the view and edit restrictions. You can then simply wrap this output in: $f = new Field(); foreach() $f->save(); so that you have: $f = new Field(); foreach([ 'type' => 'FieldtypeText', 'flags' => '32800', 'name' => 'my_field', 'label' => 'My Field Label', 'collapsed' => '0', 'minlength' => '0', 'maxlength' => '2048', 'showCount' => '0', 'size' => '0', 'tags' => '', 'editRoles' => [ 'editor', ], 'viewRoles' => [ 'author', 'editor', ], 'textformatters' => '', 'showIf' => '', 'themeInputSize' => '', 'themeInputWidth' => '', 'themeOffset' => '', 'themeBorder' => '', 'themeColor' => '', 'themeBlank' => '', 'columnWidth' => '100', 'required' => '', 'requiredAttr' => '', 'requiredIf' => '', 'stripTags' => '', 'placeholder' => '', 'pattern' => '', ] as $k => $v) { $f->$k = $v; } $f->save(); So to get this to work, create a field via the PW admin and set it up exactly how you want with the access restrictions, then go to the RequestInfo panel and copy the array from the "Field Code" section. Note that this section is not turned on by default when you install Tracy, so you will need to go to the config settings for the RequestInfo panel and turn it on.1 point
-
We can change as many forums as you like to Q&A forums but yes there were issues with it. Here's where someone hits the nail on the head when requesting the forum devs make it more like StackExchange: https://invisioncommunity.com/forums/topic/438364-qa-forum-types-add-comment-feature-please/ So SE lets you comment on the chosen answer. The forum software pulls the chosen answer out of the topic flow (from memory) and the upvoting/downvoting means you can't have a meaningful conversation in a Q&A topic. I will have a look on a local copy to see if they've updated the functionality since we last looked used it but I honestly wouldn't count on it - they seem to spend more time on implementing cross-device support for emojis than improving some useful features ?(okay so that's a bit harsh, but they do seem to have a weird priority to their feature rollouts).1 point
-
Watch out if maybe ProCache was expected to be working, because it compiles Less to CSS. Happy ProcessWiring!1 point
-
Routing on the server like you would normally do with files/folders, is not how processwire works. ProcessWire hijacks the routing as soon as any requests hits the server and the path where PW is installed, so those wire/site folders are not publicly accessible. You need to access the admin, and figure out which pages are setup in the page tree, which mainly handles the routing of the site. I insist on reading the docs above so you get a good idea on how PW works, its very simple once you dive in a little bit.1 point
-
I arrived at ProcessWire via a different path. A few years back, two other developers and I were dissatisfied with the CMS we were using. Other two researched, tested, investigated all on the market except WordPress. We all agreed we'd rather give up than go down that road. Fortunately for me, they both agreed PW was the best and I should give it a go. Haven't looked back. Thanks @ryan, the forum team, Goran and @Stikki ?1 point
-
https://processwire.com/blog/posts/rebuilding-pw-website-part2/1 point
-
If my memory serves, it was because it ruined the flow of the thread. In a lot of cases we are not looking for a single "best answer", but rather it's a discussion of different approaches. That said, it obviously works pretty well on StackOverflow so I think it's something to consider again, but I don't know which boards should use it and which shouldn't and I think that was part of the problem with the attempted implementation at the time.1 point
-
We've tried this previously. It didn't work great.1 point
-
I don't think that the existing threads and posts all can be updated to Q & A forums. For example all the modules support threads contain multiple questions and therefore multiple answers. Starting to vote posts as best answers in those threads seems to make not much sense. I'm not sure if it would be of great benefit for any existing forum. So, it will be useful when starting new subforums or boards.1 point
-
[offtopic] just wanted to mention that always when I log into a site with an older version of tracy I realize how much better the new not-so-colored theme is, thanks for that @adrian and @tpr ?1 point
-
I see, so you're packing the dependencies alongside the composer autoloader and including the autoloader on a per-module basis. That's certainly self-contained, very good solution for sites that don't use composer. Though it does mean dependencies can't be reused across modules. I guess there's something to be said for both approaches. Maybe I can put out a little module that provides a wrapper through the composer library (once it's published) so it can be installed through the Processwire GUI and called through the Processwire API. First I gotta get around to finishing it though ^^ I have started to use Composer for my latest two Processwire projects; it's a pretty simple setup, I just put the composer.json and vendor folder one directory above the webroot and then include the autoloader in the init.php file. This way it's no overhead at all, I can just use any libraries I want to and don't need to worry about anything else. Of course I have to update the composer dependencies independently from the modules, but that's just a few CLI commands away. Maybe I'll write a short tutorial for that too :)1 point
-
1 point
-
you can use it in several scenarios: Progressive Enhancement of forms: Return json for inline form validation (using the same url for the "good old form roundtrip action" and json_encoded responses: $response = array( error => true, status => 'unsubmitted', msg => 'no valid form data given' ); do { if ($_SERVER['REQUEST_METHOD'] != 'POST') break; $response['status'] = 'submitted'; if(!$someValidator->validate($_POST)) break; // more validation logic here... $response['error'] = false; } while (false); if( $config->ajax ) { if (!headers_sent()) { header('Content-type: text/json'); header('Content-type: application/json'); } echo json_encode($response); return; } Rendering different templates when urls are accessed via ajax: $template = $config->ajax ? "ui/projects_ajax.php" : "ui/projects.php"; $content = wireRenderFile( $template, array( "title"=>$title, "CategoryData"=>$pages->find("/categories/,include=hidden"), "PageData"=>$page )); ... we use this technique here (in combination with pushstate/history.js): http://www.accom.kg/ - If templates are accessed via ajax they are rendered without footer and header. This way we only load the necessary parts to be displayed. If the user (or google) visits the "real" page, navigation and footer are rendered. Redirecting users that accidentally visit some api endpoint that should only be used via ajax: if( !$config->ajax ) { $session->redirect('/'); } // API-LOGIC HERE. .... plus a billion other examples1 point
-
If you first installed PW seperately on your remote server and later imported your database tables from your local dev setup, I guess the userAuthSalt strings in your local and remote config files (right at the bottom of them) differ. As the string is used to encode your password when saved in the database as well as the one entered on login, this may cause your well-known password being rejected, when the userAuthSalt was changed. EDIT: Ah, I just saw that the topic is also addressed in the thread Arjen pointed you to.1 point