Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 11/04/2014 in all areas

  1. Bonjour Guy, To add custom fields to the user profile just go to Setup > Templates. Then click on Fit-lters section and make the admin template visible (they're hidden by default). Click on the user admin template and add any fields you might want. When you edit a user the added field should be visible. Under the ProcessProfile module settings, you'll be able to let a user update a custom field or not. The settings on your second screenshot define what fields should be visible on the list displayed when you click on Access > Users (notice the custom field "Intro" in the screenshot below) Nicolas
    3 points
  2. This is a very basic guide on how to optimize a ProcessWire page for speed. It doesn’t go into the depths of optimization and perfect render paths but will provide you with some proven ProcessWire methods for faster websites. The big problems that are easy to fix are what we aim for. You want quick improvements? Then read on… First let's have a look ath the following graph. Those are the areas, we want to improve. Source: http://httparchive.org/interesting.php?a=All&l=Oct%201%202014 Clean up your HTML Look at your HTML source code. Are there any unnecessary parts? Remove anything that might not be needed and try to keep your markup as clean as possible. Avoid using too many external JS libraries or other tools. It is okay to include jQuery from a CDN, because most visitors will already have cached the file. Too many of those external requests will slow down the page. If possible, try to avoid render-blocking Javascripts and move your script tags to the end of the page, right before the body. In most cases, your Javascript will enhance your content but doesn’t need to fire before the site is rendered. Always think if you need to include another library or the fourth webfont on your site. Minify Markup The next step to save some bytes is to remove all whitespaces from your markup. It doesn’t have to look nice, it has to be loaded fast. We perform this trick with our new super-weapon: The AllInOneMinify module for ProcessWire. Install it like every other module for ProcessWire. Once activated, go to the module settings and tick the checkbox for “Minify HTML” and look at your sites source code. It should be minified. AIOM can handle conditional browser comments. If your layout depends on whitespaces you could “force” them by putting an into the markup. Optimize the CSS Now we’re heading for the next larger part of a usual website. We will combine all CSS files and then remove anything not needed (whitespace,comments) from it. Before we start, make sure your CSS files only contain rules that you really use. Especially if you’re using a framework like Bootstrap, most of the selectors are never used. Remove them carefully. We need the AllIneOneMinify module from the previous step again. After installation, open the template file where your HTML header is generated. We will now replace all stylesheet tags with a single file. AIOM needs to know all CSS (or even LESS) files, relative to your template folder. It will then output a link to a single, compressed CSS file. You might have this in your HTML head: <link href="<? echo $config->urls->templates;?>/css/grid.css "rel="stylesheet" /> <link href="<? echo $config->urls->templates;?>/css/style.css“ rel="stylesheet" /> Replace all links to Stylesheets with the single tag like this: <link href=”<? echo AIOM::CSS(array(‘css/grid.css’,’css/style.css’)));?>” rel=”stylesheet”/> You pass an array with the file names to the AIOM method CSS. It will return a link to the file. AIOM takes care of image urls inside CSS. It will detect changes in the source file and only generate a new file if necessary. While developing, you might want to turn on the “Development” checkbox in the module settings. Make JavaScript tiny Do the same as you do to the CSS to your Javascript files. First, clean up the code. Then install AIOM and compress all JS files into a single file using the AIOM::JS method that works as the AIOM::CSS method. For best results, think about including scripts like jQuery from a CDN and put your scripts below the content, before you close the body tag. Also note that the order on how your throw your JS files into AIOM might be important, depending on the code inside. Get the right image size. ProcessWire comes with great image tools. Use them, to make images exactly the size you need them. You don’t have to serve that little thumbnail with over 3000px length just because the editor wasn’t able to reduce the size. Example: Your designer wants to have a slider image with a maximum size of 600x320 pixel. To output the image with that exact dimensions, use the API accordingly: $sliderImage->size(600,320)->url; An even better way would be to use adaptive images or the new srcset attribute combined with a JS fallback. Then your site only delivers the image size as needed. Hint: Play around with the image quality setting in the config.php. Maybe you don’t need images with a JPG quality of 90+. Compress the images further with minimize.pw To make images even smaller, we can use the minimize.pw service. This service will compress images nearly lossless by using more complicated tools to reduce the size of PNGs and JPEGs. By doing this, you remove bytes from the largest chunk of your website weight. minimize.pw is free for 2000 images. Just enter your E-Mailadress and receive a free key Then you have to install the ProcessImageMinimize module and enter they key. You can now activate the option to automatically compress every image uploaded. It is fail-safe and will compress images in the background. Please note, the automatic mode only works with images uploaded AFTER you have activated the module. You can manually select image fields with the ->mz() API method. Just include it before you output the image in your template file: $myImage->width(300,300)->mz()->url; We've closed the service. You could use something similar like Imgix ( https://www.imgix.com/ ). Activate GZip compression on your site Another method to speed up your site is to activate GZip compression. The server will then send all files compressed to the client. This works with nearly all browsers and the CPU power required is minimal. You can tell your server to do this, by adding those lines to your .htaccess file in your root directory. Please take care, that you do not overwrite the ProcessWire rules in the file! For best results add them on the top of the .htaccess file: <IfModule mod_deflate.c> AddOutputFilter DEFLATE js css AddOutputFilterByType DEFLATE text/html text/plain text/xml application/xml BrowserMatch ^Mozilla/4 gzip-only-text/html BrowserMatch ^Mozilla/4\.0[678] no-gzip BrowserMatch \bMSIE !no-gzip !gzip-only-text/html </IfModule> This was taken from another forum post. Tell the client to cache stuff To make repeating visits faster, we can tell the browser to cache special files for a longer period of time. Again, add this on top of your .htaccess file: <IfModule mod_expires.c> ExpiresActive On ExpiresDefault "access plus 1 seconds" ExpiresByType image/x-icon "access plus 1 year" ExpiresByType image/jpeg "access plus 1 year" ExpiresByType image/png "access plus 1 year" ExpiresByType image/gif "access plus 1 year" ExpiresByType text/css "access plus 1 month" ExpiresByType text/javascript "access plus 1 month" ExpiresByType application/octet-stream "access plus 1 month" ExpiresByType application/x-javascript "access plus 1 month" </IfModule> <IfModule mod_headers.c> <FilesMatch "\\.(ico|jpe?g|png|gif|swf|woff)$"> Header set Cache-Control "max-age=31536000, public" </FilesMatch> <FilesMatch "\\.(css)$"> Header set Cache-Control "max-age=2692000, public" </FilesMatch> <FilesMatch "\\.(js)$"> Header set Cache-Control "max-age=2692000, private" </FilesMatch> <FilesMatch "\.(js|css|xml|gz)$"> Header append Vary: Accept-Encoding </FilesMatch> Header unset ETag Header append Cache-Control "public" </IfModule> Remember, that this caching might be annoying while developing the site. Use the internal cache (or ProCache) Another trick to make the site faster is to use a caching system. This will “store” your rendered site so you don’t have to query the database that often. We can either do this with the internal cache of ProcessWire or use the commercial, official ProCache module. Using the build-in system, you go the the setting page of a template and open the “Cache” register. You can now set the Cache time and what happens if something changes. The settings depend on the content of the site. Mostly static content can be cached longer and you might not need to reset the cache every time. Dynamic sites will need shorter cache times. ProCache (buy here) is even faster because it will bypass PHP and the database. Files are served directly as HTML. Please note, that caching might make the site faster but it can create new problems. Use with care. Summary Keep your code as clean as possible. Remove anything unnecessary and then compress HTML,CSS and JS using the AIOM module. The largest part of your page weight are images. Keep them small by using the appropriate dimensions and consider services like minimize.pw. In the end, use intelligent caching and buy ProCache. Following this guide takes not more than an hour but can speed up your site and make your visitors happy. This was just a quick overview of techniques to optimize your page speed. There is plenty of stuff you can do but the steps above are a good first step. Maybe you can share your favorite methods (or links) to start the discussion.
    2 points
  3. I was sleepy yesterday ....Ignore some of the above... If you will never use headline counts anywhere else but in your $sidebar, then you can just uncomment the /markup/posts.php code in renderPosts() in blog.inc. This (Blog) is a site profile so you can pretty much do with it as you want...Then, use the code I wrote above to get the total counts in your $sidebar. The only thing to ensure is that you use the same PageArray for $posts for your $sidebar (total count) and your renderPosts() ($content/rest of the post) - hope this makes sense.
    2 points
  4. Shouldn't be that hard to find me today
    2 points
  5. Hi everyone, I'd like to announce a complete overhaul of this module - problem is that I am not sure whether to release it as an update to this module, or perhaps as something completely new, perhaps called PageProtector. UPDATE: The functionality described in this post is available as a separate module: PageProtector This new version (not on github just yet) makes it very easy for site editors to set up various password protected areas on their site, or to simply protect a new page or section while they are still working on it. New functionality Ability for your site editors to control the user access to pages directly from Settings tab of each page Includes whether to protect all children of this page or not Optionally allows access to only specified roles Ability to change the message on the login page to make it specific to this page Option to have login form and prohibited message injected into a custom template Access to the above "Protect this Page" settings panel is controlled by the "page-edit-protected" permission Table in the module config settings that lists the details all of the protected pages Shortcut to protect entire site with one click What do you all think - replace the existing module, or release this functionality as a separate version? Module Config Settings Page Protection Settings
    2 points
  6. There are some flavors of Windows/DOS that are not case sensitive when it comes to comparing filenames. So some operationg systems consider "processwire.gif", "ProcessWire.gif", "PROCESSWIRE.GIF" and "PROCESSwire.gif" to be the same filename. If PW would allow the case sensitive differences in file names you could imagine this will have consequences. Imagine this: I upload a file called 'ProcessWire.gif' on wamp installation, then I upload on the same page 'PROCESSWIRE.GIF', now 'PROCESSWIRE.GIF' overwrites 'ProcessWire.gif'. Filenames in ProcessWire need to be used in URL's so the filenames should be compatible with the rfc3986 standaard. This leaves us with a restricted set of characters minus the uppercase characters.
    2 points
  7. This module provides a way to rapidly generate Page fields and the required templates and pages for use as a drop down select (or any other Page field type). This module will let you create a full page field setup in literally a few seconds To use, run Page Field Select Creator from the Setup Menu Enter a Field Title, eg: Room Types Select Options - These will become the child pages that will populate the page field select options. There are two different options. Option 1. TITLE FIELD ONLY - enter one option per line, eg: Single Double Suite Option 2. MULTIPLE FIELDS - the first line is used for the field names and the first field must be 'Title'. Subsequent lines are the values for the fields, eg: Title, Number of Beds, Number of People, Kitchen Facilities Single, 1, 1, Fridge Only Double, 2, 2, Fridge Only Suite, 3, 6, Full Kitchen Choose the parent where the page tree of options will be created, eg a hidden "Options" parent page Select a "Deference in API as" option depending on your needs Choose the input field type Check whether "Allow new pages to be created from field?" should be enabled. As an example, if you entered "Room Types" as the field title, you would end up with all of the following automatically created: a fully configured page field called: room_types MULTIPLE FIELDS OPTION - 3 additional fields - number_of_beds, number_of_people, kitchen a parent template called: room_types a child template called: room_types_items (with either just a title field, or with the 3 additional fields as well) a parent page called: Room Types a series of child pages named and titled based on the per line entries in the Select Options textarea The templates are configured such that the "room_types_items" child template can only have the main "room_types" template as a parent, and vice versa. Then all you have to do is add the newly created page field to any template you want and you're ready to go! You can grab it from: Modules directory: http://modules.processwire.com/modules/process-page-field-select-creator/ Github: https://github.com/adrianbj/ProcessPageFieldSelectCreator
    1 point
  8. PageTableExtended Download here: http://modules.processwire.com/modules/fieldtype-page-table-extended/ Extends the Processwire PageTable field for rendering table row layouts. This is great for editors, because they actually see at a glance what the table rows consist of. What it does Turns the Processwire Fieldtype "Page Table" from this: into something like this (sorting capabilities of course still functional): See it in action: Requirements FieldtypePageTable installed (part of the core since Processwire 2.4.10.) Templates used for PageTable need a file associated (otherwise nothing gets rendered) This render method is meant for sites where the PageTable templates only render part of the layout, not complete websites. But you also can define what will be rendered (see below). Options Render Layout instead of table rows Check this for seeing the rows rendered. You can easily turn off the complete functionality by unchecking this. Path to Stylesheet Since the parts are unstyled by default, it is a good idea to define styles for them. All rendered templates are encapsulated in a div with the class "renderedLayout" so you can style them with: div.renderedLayout h2{ color: green; } The path is to be set relative to your templates' folder. Reset Admin CSS Since the parts are rendered inside the Admin, common styles of the Admin Interface apply also to your layout parts. This is not a bad thing, because especially text styles are well integrated in your admin's theme. But if you like to override the admin styles in your table rows completely (more or less), just check this box. Don't forget to define a custom CSS then! Advanced Since this module is meant for parts of your layout you already have defined for your frontend templates, it is a good idea to use a preprocessor like Stylus, Sass or Less for building the custom CSS file. Just outsource your layout part definitions in an extra file, compile that in a separete CSS file and use this as custom CSS for this module. Since your CSS is should be built in a modular way, this works pretty well ;-) Will write a tutorial with a use case once finished testing. Notes: Github: https://github.com/MadeMyDay/PageTableExtended If you want to get rid of the unnecessary step for entering a title before editing the page, just set the "autoformat" value as suggested in the PageTable settings. If you don't want to use a title field at all, see this post from Soma Will put it in the module repository once finished testing. Please test it and give feedback. I haven't used GitHub for a long time, please check if everything is in place and if this will work with the modules manager and the new core module installer once added to the repository. Have fun Module is in the repository now: http://modules.processwire.com/modules/fieldtype-page-table-extended/ Please use GitHub for instructions, I made some additions there.
    1 point
  9. Recipes website: http://superpola.com Modules Used: ProCache ProcessImageMinimize / minimize.pw Batcher AIOM
    1 point
  10. Hi, I don't know if this is the right section for this but I collected some thoughts and a kind of manual about how to increase the performance of your website under load with nginx and fastcgi_cache. At best, this could be a kind of ProCache for nginx users, as not everyone is using Apache and thus not able to use ProCache on their sites. Additionally, this solution comes with the benefit of server side mobile detection and selective caching. http://svn.matthiashaak.com/website-performance-with-processwire-nginx-and-fastcgi_cache/ Please let me know your thoughts or questions about this. Be aware however, that with this solution you end up serving static pages, so no hooks or PHP functions will be called. I am currently working on a module that eases the cache purging, so kindly be patient if you need this. "Wait, and thou shalt receive"
    1 point
  11. Hi, I was wondering whether there was an easy way to protect files so that they are only available to the page that links to them? For example: if I have a client page template and add a file field type to it, then create the page and attach a file - I would like to be able to secure that file so that it can only be accessed by the person viewing the page. This way I can create a secure page and file that can only be accessed by a client logging in and accessing their page.
    1 point
  12. Greets I'm busy with a new module, and I'm using PageListSelect. However, like the Page Tree, it isn't easy to select a page in a different language. To get it right, I have to go to my profile, change the language for the entire backend, and then go back to the module's form. Any way to show language tabs for PageListSelect?
    1 point
  13. I'd like to see a caching API added to Page objects. This would differ from WireCache, in that this would enable caching in a Page-specific context, which would make it possible to provide some meaningful options for (among others) cache expiration in a Page-context. The API might be something like a PageCache class, which is attached to Page objects as e.g. $page->cache. It would work much like WireCache, but would write cache entries with the Page ID attached to each entry, allowing some new options for cache expiration: Expires when the Page object is deleted Expires when the Page object is changed Expires when the Page object, or a Page in it's parent path, is changed When, for example, you have a page/template that aggregates content from another page (fetching content server-side), or when your template needs to perform expensive calculations or database queries to produce the page content, the fetched/generated content could be written as cache entries that lives forever (until the Page object is deleted) or until the next change to that Page, or a parent Page. Thoughts?
    1 point
  14. Thought it would be an error you "randomly" get on some sites, not immediately.
    1 point
  15. Would love to have PW merchandise - but Ryan has to decide
    1 point
  16. Maybe ryan could implement a option for the image/file fields to disable changing the filename. (Including a little warning and the preferred way to only use [a-z,0-9,_]).
    1 point
  17. Glad you got it sorted.. Pagination: That's why I recommended to ensure you use the same PageArray for your totals and the renderPosts(), i.e. the $posts PageArray. Anyway, test and see. Limit: It is always good to limit results. With pagination, users can always get to the next results. What you set as a limit depends on other factors such as site traffic. So, it's up to you really but rule of thumb is to limit results if you don't need to show all of them at once. Code to remove: I meant to uncomment just the code for the totals count but you have already sorted that out, no worries.
    1 point
  18. My brother produces custom textiles, so if there is a need for textile merchandise, let me know, i'll ask him for a quote.
    1 point
  19. @Wanze I just wanted to let you know that the code you posted is working as expected. Besides, it seems FieldtypePageTable also is a PageArray containing pages, so I added this one, too: <?php // bootstrap Processwire include("./index.php"); echo "Translation starts now..."; function setLanguageValue (Page $p, $language) { $pageFields = $p->fields; // iterate through all fields of a page foreach ($pageFields as $field) { $type = $field->type; // only select a field if it is translatable if ($type == "FieldtypeTextLanguage" || $type == "FieldtypeTextareaLanguage") { // only translate if the field value for the default language is not empty $defaultValue = $p->getLanguageValue(wire('languages')->get('default'), $field); if (!empty($defaultValue)) { $p->setLanguageValue($language, $field->name, "some dummy text"); } } elseif ($type == "FieldtypeRepeater" || $type == "FieldtypePageTable") { $fieldName = $field->name; // Repeater and and PageTable fields are PageArrays holding pages. foreach($p->$fieldName as $subpage) { setLanguageValue($subpage, $language); } } } $p->save(); } $p = wire('pages')->get("/"); $russian = wire('languages')->get("ru"); setLanguageValue($p, $russian); Thanks again for your help! Cheers, Stefan
    1 point
  20. This is very useful, thanks!
    1 point
  21. I've been inlining media queries in my LESS files (I haven't gotten around to using SASS yet, and because of AIOM) for a while now. As you say the CSS is a mess but I'm OK with that. I usually have a variable at the top of my LESS file: @mobile: ~"handheld, only screen and (max-width: 767px)"; When I need to use it: foo { margin-bottom: 3rem; @media @mobile { margin-bottom: 20rem; } } If I find myself needing more breakpoints I just add a variable with a different max-width.
    1 point
  22. 1. Those are not actual fields per se. No fields are created in the database. The method just 'creates' inputfields (i.e., HTML input 'areas') that are displayed in a module's configuration screen. The user configurable values in those fields are stored in the database (in that module's row in the 'modules' table in the 'data' column) in JSON-like format. On uninstall, a modules record is deleted from the database (i.e. its row in the table 'modules'), so, everything about the module is deleted: public function ___uninstall($class) in /wire/core/Modules.php/ $database = $this->wire('database'); $query = $database->prepare('DELETE FROM modules WHERE class=:class LIMIT 1'); // QA $query->bindValue(":class", $class, PDO::PARAM_STR); $query->execute(); 2. Although there are some methods (functions) specific to modules, you can use any(almost any?) PW and PHP method with modules. It is just PHP . If you are really into this, I would suggest to first study the source code of a couple of modules in the modules directory. If you are curious about some stuff have a glance at Modules.php and Module.php although you really don't need to do this. The following threads are also helpful RE configurable modules: https://processwire.com/talk/topic/5480-configurable-process-module-need-walk-through/ https://processwire.com/talk/topic/3343-how-can-i-setget-module-data-from-db-when-not-implementing-configurablemodule/ https://processwire.com/talk/topic/7581-configurable-module-default-values-on-install/ Other: https://processwire.com/talk/topic/1313-modules-process-and-the-difference/ ...which reminds me, I really need to get write those modules tutorials as promised...
    1 point
  23. Use the following in your blog-list.php if that is where you have your $sidebar $posts = $pages->find('template=blog-post, limit=10');//or whatever the template of a 'post' is $start = $posts->getStart()+1; $end = $start + count($posts)-1; $total = $posts->getTotal(); if($total) echo "<h3>" . sprintf(__('Posts %1$d to %2$d of %3$d'), $start, $end, $total) . "</h3>"; Note: getStart() and getTotal() have nothing to do with renderPosts(). They are both PageArray methods. So, you can use them with any $pages->find() operation. renderPosts(): The first parameter accepts either a PageArray, a Page or a selector string. So, the following should work... $sidebar = renderPosts($posts, true)//our $posts above...which fetched 10 posts However, I am not sure I fully understand your question as renderPosts() with $small=true should already return the counts headline?
    1 point
  24. Out of interest, do you have any details on the Bing and Yahoo parts? Google is obvious, but as far as I can tell, Bing and Yahoo still use keywords, though they're not exactly important ranking factors (quite the opposite, really -- they seem to have much less weight than regular body copy). Also, for anyone targeting the Russian or Chinese markets, it should be noted that Yandex specifically suggests using meta keywords (they're not revealing how important these are as ranking factors though) and according to some sources Baidu considers meta keywords "very important" (though keyword stuffing is a major negative signal there too).
    1 point
  25. Or even: <!-- Diogo says that I should tell you that this bit of code is to do with that very nice EMO module, okay? -->
    1 point
  26. Matt Cutts about WordPress and SEO - worth watching! Listen carefully as you will here "keywords" .... - don't mix that tool up with seoiq.de (Trittbrett Fahrer) keywords in meta data are not the same like "on-page keywords"!!! The later is still quite important, even with Google. 200 Faktors http://www.entrepreneur.com/article/226884 Daily Google is changing their algorithms so change your way of doing SEO at the same rate and you will be on the top of the pop perhaps! Goos SEO means at first place high quality content - and this content in on the visible site of all web pages and pages need to perform very good - speed! Test your sites in http://gtmetrix.com
    1 point
  27. Are you using email obfuscation? That script is the email obfuscator doing its job.
    1 point
  28. ceberlin, Just so you know, the new enhanced version (with page specific, editor managed control) is not released just yet - I am on vacation for the next two weeks, but I plan on releasing when I am back. The login process is still handled by PW, so need to do any additional sanitizing/cleaning.
    1 point
  29. Nico, I like what you are getting at, but think an option like that might be a source of confusion because it would change the entire way that templates work, as well as the way that viewability is determined. Most likely this would be problematic for PW's internal templates and logic. What I would suggest instead is repurposing of the existing $config->appendTemplateFile option and letting that serve is your defaultTemplateFile. In order to make sure that PW considers your page viewable, you'd still have to have a file for the template, but it could be completely blank. While I'd prefer the method mentioned above, another alternative would be to automatically populate the altFilename property of every template that you wanted to behave this way. For example, in your /site/templates/admin.php file you could add something like this: foreach($templates as $template) { if($template->flags & Template::flagSystem) continue; if($template->filenameExists()) continue; $template->altFilename = 'ajax.php'; $template->save(); }
    1 point
  30. Thanks Adrian, thats what I tried before. At least I thought so. Tried it again, and now it works.
    1 point
  31. Putting probablity and divisor in config.php worked for me on a ubuntu server.
    1 point
  32. Why do you feel that it's not the way you should be doing it? The only case where I think there could be a cleaner way is if you only wanted to print a comma separated list of the titles of the items inside the Page-fields. Then you could do <h4>Course Details</h4> <strong>Level:</strong> <?= $page->course_detail_level->implode(", ", "title"); ?><br /> <strong>Category:</strong> <?= $page->course_detail_category->implode(", ", "title"); ?><br /> <strong>Grouping:</strong> <?= $page->course_detail_grouping->implode(", ", "title"); ?><br /> Otherwise, just stick with the loops
    1 point
  33. The reason for this is that you are setting the divisor and the probability after the execution of the garbage collector has already been decided (in other words, after the execution of session_start()). With Ubuntu your default value for the probability is 0, meaning it will never execute. You need to place those ini_set directives before the session is started. In ProcessWire one way to do this would be wire()->addHookBefore("Session::init", function() { ini_set('session.gc_probability', 1); ini_set('session.gc_divisor', 100); }); You would need to place this inside an autoloading module though. Another way would be setting those inside your .htaccess with php_value session.gc_divisor 100 php_value session.gc_probability 1 (depending on your host, this might not work) Your last resort would be clearing them "manually" by adding this to your _init.php. Well basically you wouldn't even need a hook, you could just execute the code. wire()->addHookAfter("ProcessPageView::finished", function() { $prob = ini_get('session.gc_probability'); $div = ini_get('session.gc_divisor'); $path = ini_get('session.save_path'); $expire = ini_get('session.gc_maxlifetime'); if(rand(1,$div) <= $prob)) { foreach(glob($path.DIRECTORY_SEPARATOR."sess_*") as $file) { if(filemtime($file) <= time() - $expire) unlink($file); } } });
    1 point
  34. Hi Stefan, The repeater field is PageArray holding pages. I'm not sure if a repeater can contain another repeater, if it's possible this wouldn't be a good idea in my opinion Extract your logic into a function that can be called recursive, this is just an example written in the browser, not tested: function setLanguageValue(Page $p, $language) { $pageFields = $p->fields; // iterate through all fields of the given page foreach ($pageFields as $field) { $type = $field->type; // only select a field if it is translatable if ($type == "FieldtypeTextLanguage" || $type == "FieldtypeTextareaLanguage") { $p->setLanguageValue($language, $field->name, "some dummy text"); } elseif ($type == "FieldtypeRepeater") { // Go recursive here $repeaterFieldName = $field->name; foreach ($p->$repeaterFieldName as $subpage) { setLanguageValue($subpage, $language); } } } $p->save(); } // Execute it $startPage = wire('pages')->get("/"); $russian = wire('languages')->get("ru"); setLanguageValue($startPage, $russian);
    1 point
  35. Hi Mary, This is pretty much my standard solution: https://processwire.com/talk/topic/1716-integrating-a-member-visitor-login-form/?p=15919 It's pretty straight-forward - I think the only modifications I have made are to allow it to redirect back to the page where they logged in from. You could easily have it redirect to their member page though.
    1 point
  36. Making progress. Because each field must be an array, it appears I do need to loop through each. This is working but perhaps not the way I *should* be solving it <?php $course_level = $page->course_detail_level; $course_category = $page->course_detail_category; $course_grouping = $page->course_detail_grouping; $course_prerequisite = $page->course_detail_prerequisite; $course_writer = $page->course_detail_writer; $course_lessons = $page->course_detail_lessons; foreach($course_level as $level){ echo "<strong>Level:</strong> {$level->title}";} foreach($course_category as $category){ echo "<strong>Category:</strong> {$category->title}";} foreach($course_grouping as $grouping){ echo "<strong>Grouping:</strong> {$grouping->title}";} foreach($course_prerequisite as $prereq){ echo "<strong>Prerequisite Course:</strong> {$prereq->title}";} foreach($course_writer as $writer){ echo "<strong>Writer:</strong> {$writer->title}";} foreach($course_lessons as $lesson){ echo "<strong>Lessons:</strong> {$lessons->title}";} ?>
    1 point
  37. I'm not sure where to put this, but because I got the basic code from Ryan's post in this thread, I'll put it here. I was working on a portfolio site where the Work page spits out a list of thumbnail links. I scoured the forums looking for a simple prev/next link setup to move from page to page of the work thumbnails. I'm still learning PHP, so I can't solve these problems from scratch. Thankfully, I came across this thread and the basic solution to my problem. After tweaking Ryan's code and adding a couple of things, I came up with this: // What we are trying to grab $entries = $pages->get("/work/")->find("template=work-entry, sort=sort, limit=2"); // values we need to make this work $start = $entries->getStart(); $end = $entries + count($entries); $total = $entries->getTotal(); $num = $input->pageNum; $lastNum = ceil($total / $entries->getLimit()); // prev link if($num > 2) { $prevLink = "./page" . ($num - 1); $prevLinkClass = "class='NavPages-item NavPages-item--prev'"; $navPagesPrev = "<li {$prevLinkClass}><a href='{$prevLink}'>« Newer</a></li>"; } else if($num == 2) { $prevLink = "./"; $prevLinkClass = "class='NavPages-item NavPages-item--prev'"; $navPagesPrev = "<li {$prevLinkClass}><a href='{$prevLink}'>« Newer</a></li>"; } else { $navPagesPrev = ""; } // next link if($num < $lastNum) { $nextLink = "./page" . ($num + 1); $nextLinkClass = "class='NavPages-item NavPages-item--next'"; $navPagesNext = "<li {$nextLinkClass}><a href='{$nextLink}'>Older »</a></li>"; } elseif($num == $lastNum) { $navPagesNext = ""; } Then you can output the links with <ul class="Nav NavPages"> <?php echo $navPagesPrev; echo $navPagesNext; ?> </ul> When you're on the first page, the prev link won't show up, and when you reach the last page, the next link will disappear. I used a small limit to make sure it worked for over 2 pages of links. I hope somebody will find this useful.
    1 point
  38. Or just use $log ? $timer = Debug::timer(); ... $log->save("mylog", "phase 1: " . Debug::timer($timer)); $timer = Debug::timer(); ... $log->save("mylog", "phase 2: " . Debug::timer($timer)); Will create a log in site/assets/logs/ as mylog.txt
    1 point
  39. To implement a module to do this, I would need to hook the path generation at the lowest level, which appears to be PagefilesManager::path() or actually the static method PagefilesManager::_path() at the very lowest level? Ryan, any chance you can make this hookable? A module could then implement the path modification, e.g. adding ".protected/" to the path, and adding a new setting to FieldtypeFile, and a checkbox to InputfieldFile. Does that sound feasible?
    1 point
  40. There's an issue at GitHub related to filename conversions: https://github.com/ryancramerdesign/ProcessWire/issues/305. Technically this would be an IRI, no longer an URI (like Martijn pointed out above), but supporting that in the specific case of files might actually make sense. Personally I'm more interested in supporting non-ASCII characters in filenames than uppercase/lowercase. I'm not familiar with the issues Martijn mentioned, but it would be interesting to know how widely spread they are. If they affect Windows > XP, then it's probably worth considering
    1 point
  41. 1) a) I think the best approach is to store all the content pages under one hidden parent using the Details > Select a Parent for Items b) Not really an issue if you do a) c) Make use of Input > Automatic Page Name Format, and then go to the template context settings for the title field and make it invisible and not required. 2) This can be handled by setting the allowed parents for these content block templates. Hope that helps.
    1 point
  42. 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
  43. public function ready(){ if(wire("page")->template == "admin") return; wire("page")->template = "ajax"; } done. Not sure about consequences. Page viewable is set by if template exists or not.
    1 point
  44. RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC] RewriteRule ^(.*)$ http://%1/$1 [R=301,L] Just for the record, you might want to consider the benefits of using www-subdomain before doing this, though.
    1 point
×
×
  • Create New...