Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 09/08/2014 in all areas

  1. I've been working on a module to make it really simple to upgrade ProcessWire from one version to another. Especially as a way to make it easy to upgrade from PW 2.4 to 2.5, or to upgrade from one dev version to another. This tool supports upgrading between any branches of ProcessWire (currently we only have master and dev on GitHub). It will also let you downgrade your ProcessWire version, though no reason to do that. The module keeps up-to-date directly with GitHub, so it works as a long-term tool for every upgrade if you want it to. It works best if your file system is writable. However, if it isn't, the tool can still be used. It will still download the upgrade files to the server and then tell you where to move them. I should also mention that this module is somewhat inspired by a similar module Nico built awhile back called AutoUpgrade. So far I've used this tool to upgrade this site (processwire.com), the skyscrapers site, and the modules site (modules.processwire.com). Before releasing this officially in the modules directory, or suggesting it for production use, I'd like to get some help testing. If anyone has availability to help test this on non-production sites, your help is appreciated. It can be downloaded from GitHub here. As a bonus, it will also be a good opportunity to help test PW 2.5! Thanks in advance. What I'd really like to do as the next step with this is make it support upgrade by FTP. That would provide a nicer and safer solution for those that don't have writable file systems on their servers. This tool should be compatible with ProcessWire versions as far back as 2.3.4. I will also update it to support older versions than that if there's demand for it.
    11 points
  2. Just installed the Default version of 2.5 and wanted to say what a nice job has been done of the front end default styling. Not sure who's responsible as I've been somewhat out the loop but I think it's a nice first "Welcome to PW', with a very modern and minimal feel. Less opinionated than the classic in my opinion. Good job
    5 points
  3. Another possible and very simple way to setup a Frontend-login: Use the ProcessLogin.module from core within a login Template. <?php /** * Frontend Login template * */ include("./head.inc"); echo = $modules->get('ProcessLogin')->execute(); include("./foot.inc"); or to prevent from redirecting with a few lines more code <?php /** * Frontend Login template * */ include("./head.inc"); //to prevent from redirecting to backend, happens anyway only if loggedIn User has permission page-edit function noRedirect($event) { $event->replace = true; $event->return = $config->urls->root; } $login = $modules->get('ProcessLogin'); $login->addHookAfter('afterLoginRedirect', null, 'noRedirect'); echo $login->execute(); include("./foot.inc"); same works with Profile after login echo $modules->get('ProcessProfile')->execute(); Don't reinvent the wheel like me very often. To customize the output look here http://processwire.com/api/hooks/
    5 points
  4. @clsource Transactions cover quite a wide area but using DB transactions isn't the only way to address the race condition for that last item or items that you have in your use-case. Here's a solution using a module I'm developing and hope to release commercially. How does this look? /** * Somewhere in your application you load the module */ $counters = $modules->get('ThreadsafeCounters'); /** * In add-to-cart logic you request a given qty of product. * You may get zero (if all taken), the number you requested (if many still left) * or some number in between (if there are too few left to fulfil entire request.) */ $reserved = $counters->reserve('product_qty_remaining', $number_requested); if (0 == $reserved) { /** * All taken - sorry! */ } else if ($reserved == $number_requested) { /** * Entire number can be fulfilled. */ } else { /** * Only a partial fill is possible. * If you don't want to handle this case in your application you either return * the $reserved qty straight away or call reserve() with the $all_or_nothing * flag set to true: $reserved = $counters->reserve(<counter_name>, $qty, true); */ } /** * If a sale falls through later (perhaps payment rejected) simply return the * number the customer ordered... */ $counters->inc('product_qty_remaining', $qty_of_product_in_order); This uses thread-safe, persistent, counters to prevent races and simplify application logic.
    4 points
  5. That was funny, I took quite some time to debug this, but finally I knew what was wrong... On two pages I got an error like the text below. Specifically telling me the sort order... Error: Exception: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'pages.children' in 'order clause' (in C:\xampp\htdocs\mysite\wire\core\DatabaseQuery.php line 91) First I thought, must be because because I did not have pages containing this value. But it was never like that with PW. It would simply not let me see it if not found - it's the ease of PW! So then I deleted those pages, added new ones, no solution. Looked in the DB - nothing strange there... Looked at my selectors - nothing is wrong... What was the trouble??? Answer: reserved words! I had a parent page named "household", with you can guess it: a child named "children" and "parents". stupid stupid stupid. lol I guess I have to check my page names carefully: because a pages->find "parents" or "children" works as string, just not on the sort... in a DB action... - edit - so this was the problem : 1. goal: I want to sort on field value 2. goal: looking for template = member-profile 3. goal: using browse template for this 4. I am actually on the pages (using browse) which are used as a field value for member-profile pages... 5. assuming I am on /browse/household/children/ THIS $pages->find = " template=member-profile, {$page->parent->name} = {$page->name} " READ $pages->find = " template=member-profile, household = children " sort = "{$page->name}" // gives error - apparantly translates to sort on children(). I can't sort on children() pages I did not request. but here's the thing .... 5b. assuming I am on /browse/household/roomies/ sort = "{$page->name}" // gives no error - it translates to sort on roomies. And will work ... ?????
    4 points
  6. I don't have problems with it? Have you by any chance accidentally clicked some of the Other options? This gotcha hit me in the past (as well) Other Just items I follow Items I participated in Items I started
    4 points
  7. Hi kixe, Seems like a cool approach to things, but I just did a little testing and am having some issues - maybe you made some changes to your code just before posting. Firstly, you need wire('config') because it's inside a function. It can't get the root url the way you have it. $event->return = wire('config')->urls->root; Also, the redirect still happens with the code you have. If I change it to a "before" hook it doesn't redirect, but you are stuck with the "Continue" link on the page. Looking at the edit Profile option - not sure I'd want any front-end only users to have the options to change the admin theme, which will show up in that form if you have more than one installed. It won't be relevant to them and just confusing. It might seem like more work, but there are simple ways to create your own custom login and profile edit form with not too much code. I have based most of mine off this post by Ryan: https://processwire.com/talk/topic/1716-integrating-a-member-visitor-login-form/?p=15919
    3 points
  8. You want to Google 'Responsive Web Design' ProcessWire is up to any task ...but it has nothing to do with output. It will output whatever you throw at it so.... But here's a great classic if you've not seen it before: http://alistapart.com/article/responsive-web-design
    3 points
  9. Launched http://www.greggorrauto.com last week! Responsive Theme built with Bootstrap 3 and Processwire! Uses the bootstrap carousel for the slider, and the Affix.js to keep the right column on the inventory search page sticky on scroll. (If the screen is tall enough.) Also uses a modal style lightbox on the inventory detail page as well as animated scrolling to anchors. I know I used the Google maps marker module and the form templates processor module. Also using redirects and batcher. (Redirects for the sub menu items for the price ranges. It just sends the user to the search page with the correct query strings. The homepage slider is managed with the image field so I can drag and drop new slides up, but I didn't know how to manage both the caption and the link url using just the description field, and I did not know how to add another one, so I did a pipe delimited. ie. image caption|http://www.linkurl.com format is used in the image description field. If its easy to add a second box to separate those out, let me know! Also, let me know what you think!
    3 points
  10. ProcessWire uses quite basic RBAC system and it probably just didn't feel necessary to dive further into this. Some of the basics: Each user has one or more roles; "guest" is always assumed and required, even for non-logged-in users (i.e. visitors) Each role is a named collection of one or more permissions; page-view (as you noted before) is always assumed and required and only displayed because, well, it's there (that's actually supposed to be helpful; you don't have to guess which permissions this role might have, what you see is what you get) Permissions are just permissions, there's nothing really magical about them; for the most part they're just Pages with special purpose Each Page uses a Template and each Template has access settings, where you can define which roles have access to the basic actions on Pages using said template: view, edit, create and add children One important thing to note here is that an user having a role with page-edit (or page-view) permission won't instantly allow that user to edit / view all pages but it is a prerequisite for giving this kind of access at Template level (via access settings). Template level access settings are just one use case for the access control system in ProcessWire; it actually goes a lot further and is much more versatile than that. (Admittedly this part does sometimes cause confusion and thus it might be worthwhile to document it more clearly.) Programmatically managing and/or checking for roles/permissions is explained in the docs. If you want to check if user has specific permission, whether that's built-in permission or one you've added yourself, it goes like this: $john = $users->get("johndoe"); if ($john->hasPermission("read-the-docs")) { echo "Sure thing, go ahead: http://processwire.com/api/"; } Cheatsheet also provides basic info on most (if not all) actions you can perform on/with users, roles and permissions. If you use $pages->find(), it should already only return pages that current user has view access to (unless you add "include=all"), so I'm not entirely sure what you're referring to in your last comment. Pages don't have roles, they have a Template, and that Template has access settings. If current user doesn't (via one of her roles) have access to view that Page, it won't be returned by $pages->find() either. Note: $pages->get() is different from $pages->find(), as it assumes you really want that one, specific Page. It always returns the Page (if it exists) without considering permissions.
    3 points
  11. Couple of bits of wording jump to mind. Perhaps: Instead of "the found version....." have: "The available version is the same as your current installation" Instead of "we recommend you make another backup on your own too...." Have: "For additional safety, we recommend creating an independant database backup, for instance with PhpMyAdmin" Good tool though!
    2 points
  12. Try the attached module - works here. Let me know if that works at your end. CustomPageListButtons.module
    2 points
  13. Thanks for sharing a really beautiful site with us! I like this project for so many reasons, but the main one is it is a perfect showcase of what you can do in ProcessWire with a little knowledge and time. 15 days to convert everything from Drupal to ProcessWire? Wow, that's quite something for this site. Did you have all the content already in Drupal so it was a case of moving everything over? Or was it more 15 days to get ProcessWire set up for all of the various content types and data entry came later? I know you can build things very fast in ProcessWire and with a dedicated team of people working on it it must be an even faster experience Again, a perfect example to anyone wondering what relatively-unknown system can do - certainly another site I will be pointing people to to allay any fears around whether ProcessWire is capable of delivering complex sites. Hope you don't mind, but I linked to the site a couple of times in your original post - once when you first mention the revamped site and also made the screenshot clickable to the site, just so folks don't miss it. EDIT: When you get to the 404 page, it says "NULL" in the top-left corner. I saw it due to a typo, so no broken links or anything like that
    2 points
  14. I recently had to setup front-end system to handle logins, password resets and changing passwords, so here's about how it was done. This should be functional code, but consider it pseudocode as you may need to make minor adjustments here and there. Please let me know if anything that doesn't compile and I'll correct it here. The template approach used here is the one I most often use, which is that the templates may generate output, but not echo it. Instead, they stuff any generated output into a variable ($page->body in this case). Then the main.php template is included at the end, and it handles sending the output. This 'main' template approach is preferable to separate head/foot includes when dealing with login stuff, because we can start sessions and do redirects before any output is actually sent. For a simple example of a main template, see the end of this post. 1. In Admin > Setup > Fields, create a new text field called 'tmp_pass' and add it to the 'user' template. This will enable us to keep track of a temporary, randomly generated password for the user, when they request a password reset. 2a. Create a new template file called reset-pass.php that has the following: /site/templates/reset-pass.php $showForm = true; $email = $sanitizer->email($input->post->email); if($email) { $u = $users->get("email=$email"); if($u->id) { // generate a random, temporary password $pass = ''; $chars = 'abcdefghjkmnopqrstuvwxyz23456789'; // add more as you see fit $length = mt_rand(9,12); // password between 9 and 12 characters for($n = 0; $n < $length; $n++) $pass .= $chars[mt_rand(0, strlen($chars)-1)]; $u->of(false); $u->tmp_pass = $pass; // populate a temporary pass to their profile $u->save(); $u->of(true); $message = "Your temporary password on our web site is: $pass\n"; $message .= "Please change it after you login."; mail($u->email, "Password reset", $message, "From: noreply@{$config->httpHost}"); $page->body = "<p>An email has been dispatched to you with further instructions.</p>"; $showForm = false; } else { $page->body = "<p>Sorry, account doesn't exist or doesn't have an email.</p>"; } } if($showForm) $page->body .= " <h2>Reset your password</h2> <form action='./' method='post'> <label>E-Mail <input type='email' name='email'></label> <input type='submit'> </form> "; // include the main HTML/markup template that outputs at least $page->body in an HTML document include('./main.php'); 2b. Create a page called /reset-pass/ that uses the above template. 3a. Create a login.php template. This is identical to other examples you may have seen, but with one major difference: it supports our password reset capability, where the user may login with a temporary password, when present. When successfully logging in with tmp_pass, the real password is changed to tmp_pass. Upon any successful authentication tmp_pass is cleared out for security. /site/templates/login.php if($user->isLoggedin()) $session->redirect('/profile/'); if($input->post->username && $input->post->pass) { $username = $sanitizer->username($input->post->username); $pass = $input->post->pass; $u = $users->get($username); if($u->id && $u->tmp_pass && $u->tmp_pass === $pass) { // user logging in with tmp_pass, so change it to be their real pass $u->of(false); $u->pass = $u->tmp_pass; $u->save(); $u->of(true); } $u = $session->login($username, $pass); if($u) { // user is logged in, get rid of tmp_pass $u->of(false); $u->tmp_pass = ''; $u->save(); // now redirect to the profile edit page $session->redirect('/profile/'); } } // present the login form $headline = $input->post->username ? "Login failed" : "Please login"; $page->body = " <h2>$headline</h2> <form action='./' method='post'> <p> <label>Username <input type='text' name='username'></label> <label>Password <input type='password' name='pass'></label> </p> <input type='submit'> </form> <p><a href='/reset-pass/'>Forgot your password?</a></p> "; include("./main.php"); // main markup template 3b. Create a /login/ page that uses the above template. 4a. Build a profile editing template that at least lets them change their password (but take it further if you want): /site/templates/profile.php // if user isn't logged in, then we pretend this page doesn't exist if(!$user->isLoggedin()) throw new Wire404Exception(); // check if they submitted a password change $pass = $input->post->pass; if($pass) { if(strlen($pass) < 6) { $page->body .= "<p>New password must be 6+ characters</p>"; } else if($pass !== $input->post->pass_confirm) { $page->body .= "<p>Passwords do not match</p>"; } else { $user->of(false); $user->pass = $pass; $user->save(); $user->of(true); $page->body .= "<p>Your password has been changed.</p>"; } } // display a password change form $page->body .= " <h2>Change password</h2> <form action='./' method='post'> <p> <label>New Password <input type='password' name='pass'></label><br> <label>New Password (confirm) <input type='password' name='pass_confirm'></label> </p> <input type='submit'> </form> <p><a href='/logout/'>Logout</a></p> "; include("./main.php"); 4b. Create a page called /profile/ that uses the template above. 5. Just to be complete, make a logout.php template and create a page called /logout/ that uses it. /site/templates/logout.php if($user->isLoggedin()) $session->logout(); $session->redirect('/'); 6. The above templates include main.php at the end. This should just be an HTML document that outputs your site's markup, like a separate head.inc or foot.inc would do, except that it's all in one file and called after the output is generated, and we leave the job of sending the output to main.php. An example of the simplest possible main.php would be: /site/templates/main.php <html> <head> <title><?=$page->title?></title> </head> <body> <?=$page->body?> </body> </html>
    2 points
  15. I’d say give the current dev version a whirl and update when 2.5 is released. Check out the dev branch thread in the announcements forum. A bunch of people are already running dev on production sites, as it seems. https://github.com/ryancramerdesign/ProcessWire/tree/dev https://processwire.com/talk/topic/3768-processwire-dev-branch/page-13 edit: eh, beaten. Copy and paste is a bit tedious on mobile
    1 point
  16. No need to wait - just start using 2.5 now - lots of us are using it in production: https://github.com/ryancramerdesign/ProcessWire/tree/dev
    1 point
  17. Well, this social network is a result of more than 2 years of development (alone), I can write something about but I'm not a top level programmer , I'm pretty sure a lot of stuff I created can be made in a better way. I can stop the website few hours in the night...anyway I'm migrating to a better server so I will make all the test there and when ready move everything.
    1 point
  18. Mr. Cramer is guilty for that. And his brother.
    1 point
  19. Hey Guys, The site isn't brand new, but runs for four months now. The client is a facility management & building-cleaning company from Hamburg, Germany. We had reworked the Corporate Design before we started the creation of the website. Quite modest colors characterize the website. Besides that, there is nothing really special about the site. ProcessWire 2.4 Responsive Layout a few "Cross-fields" (display data on different pages, but get it all from one central place to avoid redundant data like contact informations) Modules: Hanna Code Redirects (to keep the search engine ranking) Modules Manager ModestAdminTheme (my absolute favorite Admin theme) and most important: ProcessPreview by nico! Big thanks again for finalizing this nice module! This site will be constantly reworked and extended with smaller and bigger things. oellerking.de
    1 point
  20. Thank you for your feedback! Very good advice!
    1 point
  21. https://processwire.com/talk/topic/7164-processwire-and-seo/
    1 point
  22. Hey Nico - I just submitted a PR to fix the uninstall problem: https://github.com/NicoKnoll/ProcessPageDelete/pull/11 Just a matter of adding an "include=hidden" when looking for the page. I guess this is a fairly new issue from when you added the hidden status to the page when Ryan added the new "Tree/Find" submenus to the admin.
    1 point
  23. Or here: Check out the drop down at the top right which allows you to choose the template which the settings will be applied to.
    1 point
  24. it is, but not much written about it https://processwire.com/api/variables/user/ What you see is the pagename, it's just a page object, as it extends Page. If you give a user a permission, you could check if the user has that permission. As permissions is the parent of a permission, you could get that permission by page name. (Pagenames under the same parent are unique). It's a permission you could set on template level. You could ask if $page->editable() (for current loggedin user), which returns true or false. So this can be done on front-end and happens in the backend to. It is used for example in the hookable ProcessPageListRender::getPageActions. (Pages list) So, if the user has edit rights, show the edit button after the page.
    1 point
  25. Nico - one thing I did notice is that if you uninstall the module and go to reinstall you get an integrity violation. At least for me, the Delete page that is added during install is not being removed properly, so when it goes to add it again, that causes the error. If I manually delete the page, then the re-install works fine. I haven't tested thoroughly and just heading out for the day, but might be something you can look into.
    1 point
  26. I think it will happen less from now on
    1 point
  27. One little point: There's a lot of `console.log` going on. Somehow there's in my mind that that could break processing of javascript in old versions of IE. (Maybe i'm wrong) Never the less I want to mention it Posted this to the wrong post. Hell yeah, I like tabs in browsers
    1 point
  28. This works for me. This replaces all the existing buttons and adds a new one called "custom". Is that what you are looking for? public function init () { parent::init(); wire()->addHookAfter("ProcessPageListRender::getPageActions", function($event) { // anonymous function $event->replace = true; $new_action = array( 'cn' => 'custom', 'name' => 'Custom', 'url' => '/my/path' ); $event->return = $new_action; }); }
    1 point
  29. This sounds like a good case study for PW...if you could do a write-up about creating a social network site with PW that would be great . Btw, when ready to migrate to 2.5, are you saying you couldn't even warn users in advance that the site will be offline for a set number of hours?
    1 point
  30. It would be nice if the required `title step` can be avoided when using multiple templates. But maybe this is out of scope of this module as it is a thing ProcessWire could handle.
    1 point
  31. So long as the field isn't a repeater, file/image, or PageTable, PW 2.5 (2.4 dev) can do it in one query, which should take about a second. PW 2.4 and prior cycled through each page to delete a field. So that could be a slow process, though it is a good process. PW 2.5 still has to cycle through every file/image or repeater/pagetable field since they all involve external assets that also need to be deleted. But if the field you need to delete isn't one of those, you may want to consider waiting for PW 2.5 since we may soft launch it as soon as next week. Or you could try out the dev branch locally to test things out and see if you want to use it live.
    1 point
  32. No need for a form. <div class='myViews'> <a class='button switchLayout' href='#' data-view='list'>List view</a> <a class='button switchLayout' href='#' data-view='grid'>Grid view</a> </div> jQuery: $('myViews').on('click','.switchLayout',function(e){ e.preventDefault(); var whichView = $(this).attr('data-view'); $.get( document.URL, { layout: whichView }).done(function( data ) { $( ".myView" ).html( $(data).filter('.myView').html()); }); }) in your template: ... $layout = $sanitizer->text($input->layout); // is there a get variable from ajax? if($layout){ $session->layout = $layout; } else // or something in session? { if($session->layout){ $layout = $session->layout; } else { // standard view $layout = "grid"; } } include("./inc/{$layout}.inc"); // returns $layoutView ... html goes here ... <div class="myView"> <?= $layoutview ?> </div> ..... So basically: Fetch the click, identify the button, load the current page via Ajax and with a GET variable which tells the template which view to render. The response is filtered, so only the myView part is the replacement for the current .myView. Written in the browser, totally untested.
    1 point
  33. You can also remove the fields using the API.... Backup your site first, please! This was written in a function context so feel free to change it and use in a template file context. You could also wrap the code in a conditional if $user->isSuperuser... Changed and done... if ($user->isSuperuser()) { //first remove the fields from 'user' template before deleting them. $t = $templates->get('user'); $fg = $t->fieldgroup; $fg->remove($fields->get('your_field')); $fg->save(); //delete the fields $f = $fields->get('your_field'); $fields->delete($f); }
    1 point
  34. I've made something like this for me as well. Another interesting thing is sharing with WhatsApp. If you don't want to push it to the wide audience, but to a special friend or group... Unfortunately it just works on iPhones. I haven't try it yet, but want to use it in my next project. The HTML Part: <a href="WhatsApp://send?text=Text durch native Deeplink!" class="WhatsAppLink" style="display:none;" >Send</a> The JS: (navigator.userAgent.match(/(iPhone)/g)) ? $(".whatsappLink").fadeIn() : null ;
    1 point
  35. Hi Tobaco, my setup is always the same. Doesn't matter if I use PageTable or not. Here it goes (simplified): /templates - basic-page.php - home.php - /tpl - main.php - mainnav.php - subnav.php - footer.php The tpl/main.php is the overall template like: <?php include('tpl/mainnav.php'); include('tpl/subnav.php'); include('tpl/slider.php'); ?> <!DOCTYPE html> <html class="no-js"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <title><?= $page->title ?></title> <!--- styles and scripts --> </head> <body class='<?= $bodyclass ?>'> <header> <div class='wrap'> <a href="/"><img src='/site/templates/img/logo.png' class='logo' alt="Logo"></a> <nav class='main'> <?= $mainnav ?> </nav> </div> </header> <?= $slider ?> <?= $subnav ?> <section class="content"> <div class="wrap group"> <h1 class='v2 hide'><span><?= $page->title ?></span></h1> <?= $content ?> </div> </section> <footer> <div class="group"> <?php include ('tpl/footer.php'); ?> </div> </footer> <script src="/site/templates/dist/all.min.js"></script> </body> </html> basic-page template looks like this (every template renders the content and then includes the main template): <?php /** * basic page template * */ $bodyclass='inner'; $content = $page->body; include('tpl/main.php'); With PageTable the structure looks like this: /templates - basic-page.php - home.php - part_text.php - part_columns.php - part_gallery.php - /tpl - main.php - mainnav.php - subnav.php - footer.php The part_* templates are templates only for PageTable. part_columns.php could look like this: <?php $headline1 = ""; $headline2 = ""; if(!$page->checkbox1) $headline1 = "<h2>{$page->title}</h2>"; if(!$page->checkbox2) $headline2 = "<h2>{$page->text1}</h2>"; // Output echo " <div class='pageTableSection {$page->template->name}'> <div class='inner'> <div class='col one-half'> {$headline1} {$page->body} </div> <div class='col one-half'> {$headline2} {$page->textarea1} </div> </div> </div> "; And the basic page template gets enhanced by ("layout" being the PageTableExtend field): <?php /** * basic page template * including PageTable layout parts */ $bodyclass='inner'; $content = "{$page->body}"; if(count($page->layout)>0){ foreach($page->layout as $l){ $content .= $l->render(); } } include('tpl/main.php'); That way, the layout parts are easily renderable in the Admin with PageTableExtended. While writing this, I want to point to another feature of the module. If rendered by PageTableExtended, the template gets an option 'pageTableExtended' which you can use in your part template: // Output echo " <div class='pageTableSection {$page->template->name}'> <div class='inner'> <div class='col one-half'> {$headline1} {$page->body} </div> <div class='col one-half'> {$headline2} {$page->textarea1} </div> </div> </div> "; if(!$options['pageTableExtended']){ // we are not in the Admin, so we include our social media buttons which we only need in our frontend include('social/socialmediabuttons.php); } Hope that helps.
    1 point
  36. Hard to tell Did you echo out $_POST or checked the request with DevTools/Firebug if there are really no values sent? Often this happens because people forget to add a trailing slash to ProcessWire urls in the form action. In this case, Pw does a redirect and you loose post variables. One thing you could try is changing: action="./" to action="<?= $page->url ?>" although I'm pretty sure it's not the issue...
    1 point
  37. so you get your emails but without any values in it?
    1 point
  38. I said: I formulated this wrong, sorry. What I really meant is that this is easy to accomplice with the ProcessWire API. Examples: 'Redirect to the first child'. In MODX you need a module 'FirstChildRedirect', the ProcessWire way: $session->redirect($page->child->url); To get the highest parent of an page in the tree. In MODX, you could make it yourself difficult with code or install UltimateParent. The processWire way: $page->rootParent; Create a Gallery of images: In MODX you can install 'Gallery' and study the documentation. The ProcessWire way: echo "<ul>"; foreach ($page->images as $image) { $thumb = $image->size(100,100); // create thumbnail echo "<li>"; echo "<a href='$image->url'>"; echo "<img src='$thumb->url' alt='$thumb->description'>"; echo "</a>"; echo "</li>"; } echo "</ul>"; The template language of MODX is MODX only, outside of MDX this knowledge is almost useless. You don't need to know much PHP to get the 'same' results in ProcessWire. But if you drop ProcessWire for some reason, you've build some experience with PHP. And that is valuable.
    1 point
  39. sooooo, maybe this is overkill or totally Wrong but i got it to work. offcourse in a module as it should if someone needs this feel free to use: <?php /** * Created by PhpStorm. * User: Blackeye1987 * Date: 04.08.14 * Time: 10:09 */ class CustomStartpoint extends WireData implements Module, ConfigurableModule { public static function getModuleInfo() { return array( 'title' => 'CustomStartpoint', 'version' => 100, 'summary' => "Access Startpoint for Users *needs (type:page | single page or boolean | Input field type PageListSelect+) set to user template* *Consider Taking in Account using ALSO ryancramers PageEditPerUser.module for extended User Control -> https://github.com/ryancramerdesign/PageEditPerUser/", 'href' => '', 'singular' => true, 'autoload' => true, ); } public static function getModuleConfigInputfields(array $data){ $inputfields = new InputfieldWrapper(); $field = wire('modules')->get('InputfieldSelect'); $field->attr('name', 'startpoint_field'); $field->label = __('Starting Point'); $uT = wire('templates')->get('user'); $fL = $uT->fields; foreach($fL as $f){ $field->addOption($f->name,$f->name); } //set your named custom field for the startingpoint of the user $field->attr('value', isset($data['startpoint_field']) ? $data['startpoint_field'] : ''); $inputfields->add($field); return $inputfields; } public function init() { $this->addHookBefore('ProcessPageList::execute', $this, 'startpoint'); } public function startpoint($event){ $page = $event->arguments[0]; //startpoint page $sp_p = $this->get('startpoint_field'); $id = $this->user->get($sp_p)->id; //if no page is set run normally if(!$this->user->get($sp_p)){ return; } if(!isset($_GET['id'])){ $_GET['id'] = $id; } //if user tries to overwrite id, still edit needs to be allowed //--can be handled through ryans module! //do not allow them to edit the pages and you are done if($_GET['id'] != $id && !strpos($_SERVER['REQUEST_URI'],'/page/edit/') > 0){ $this->message(__('You are not allowed here')); return; } //bugfix pw ? //open needs to be removed because: //if open is a childid of id, id will be opened twice (why ?) unset($_GET['open']); $_GET['id'] = $id; if(strpos($_SERVER['REQUEST_URI'],'open=') > 0){ $this->session->redirect(substr($_SERVER['REQUEST_URI'],0,strpos($_SERVER['REQUEST_URI'],'open='))); } return; } } readme: 1: Create new Field : type: Page Details (Single Page or boolean) Input: Select Parent (Home is fine because as admin you set this Value) Input: Input field type PageListSelect 2. Assign to UserTemplate 3. Set Startingpoint for the User who needs the Startingpoint 4. Login with User who should now have a Startingpoint 5. Wish me Luck no one will kill me for this Code if anyone wants to proof read the code or has any questions or suggested improvements, just reply.
    1 point
  40. zyON, Check into the Page Fieldtype Maybe something like this for organization: Shoes -- Men ---- Product A ---- Product B ---- Product C -- Women ---- Product A ---- Product B ---- Product C Brands (these are just the references, no products listed as children) -- Brand 1 -- Brand 2 -- Brand 3 Collections (these are just the references, no products listed as children) -- Collection A -- Collection B -- Collection C Create page fields for Brand and Collection, and add them to your "Product" template. Now you can associate brand and collection with each product. So to get the output you need: Shoes > Men (Any Brand) $pages->get("/shoes/men/") Shoes > Brand2 $pages->find("has_parent=/shoes/, brand.title=Brand 2") Shoes > Brand2 > CollectionB $pages->find("has_parent=/shoes/, brand.title=Brand 2, collection.title=Collection B") You could also pass $input values to the selector so this could be generated via use selections.
    1 point
  41. I also had the Problem with umlauts and strftime. The solution that worked for me was this line of code: setlocale(LC_ALL, 'de_DE.UTF-8'); Hmm PHP why isn't everything utf-8 by default...
    1 point
  42. That's correct that the 1% is taken out and substituted as left margins instead. This is for all columns except for the first in a row. I've actually been planning to switch to width classes rather than the inline styles that are used now. The primary reason is just to be able to support breakpoints with responsive layouts. For instance, if you've got a screen width under 600 px or something like that, you might want to cancel the floating behavior of all widths less than 100%, and instead just make them take up a full row. We can do that if we're using classes, but not if we're using inline styles. @interrobang: Check the markup settings in the Form Builder module settings. This may let you add the extra wrappers you want. Also want to mention that just because Zurb Foundation or Bootstrap (or another) provide some form features and grids doesn't mean that you have to use them with Form Builder. I personally think you are a lot better off with Form Builder's defaults than you are with those of Foundation or Bootstrap. Those frameworks are just trying to cover common form needs for the masses, but Form Builder goes well beyond this. As soon as you start letting a general purpose CSS framework take over your form styling needs, you are then limiting Form Builder's output capabilities to those of your framework. Though if you are dealing with fairly basic forms (primarily text fields) and simple needs, then there's also no harm in using a CSS framework for form styling either. But I think you will be happier if you give this control to Form Builder rather than [insert CSS framework here].
    1 point
  43. It's possible to use <repeater-name>.<field-in-repeater> as a field name. For example: $matches = $pages->find("title|my_repeater.my_field~=$q");
    1 point
  44. I wasn't sure what first what you meant by switcher, but now I think I get it. Assume I understand correctly, you need something to target the switch like a GET variable, i.e. domain.com/?theme=pretty Then before you send any output (like before your <doctype>) you'd check for that GET variable and stuff it in the session. if($input->get->theme) { // set the theme $session->theme = $sanitizer->pageName($input->get->theme); } Now that value in $session->theme will be retained regardless of what page they click on, or at least until they set another. When you get into the <head> part of your document where you are going to be outputting the stylesheet links, you would just check the value of $session->theme: if($session->theme == 'grunge') { $css = 'ugly.css'; } else if($session->theme == 'pretty') { $css = 'baby-unicorn.css'; } else { $css = 'default.css'; } echo "<link rel='stylesheet' type='text/css' href='{$config->urls->templates}styles/$css' />";
    1 point
×
×
  • Create New...