Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 10/17/2017 in all areas

  1. Released: https://modules.processwire.com/modules/process-documentation/ https://github.com/outflux3/ProcessDocumentation This is a new module that will be released soon - the purpose is to allow you to create help pages in the admin. This differs from the Admin Help module in the approach, and will be kept totally separate. The Admin Help modules provides the ability to make a help tab on any page edit screen (and optionally make that pop up in a lightbox), as well as a single process page showing all of the help pages in a single accordion. This module's workflow is different - first you can create your help pages any way you want using any template and any field for the body text. You can create unlimited admin help pages, using ProcessDocumentation, select the page to display, and then users can click on that in your menu to access the help page. You can create a folder structure by creating a top level menu item using ProcessList, and then various help pages under that parent using ProcessDocumentation. The module comes with 2 internally used textformatters, one of them adds classes needed to the markup for some elements to allow styling within the content and not conflict with admin theme rules (e.g. ol, ul, blockquote, table etc.). The other textformatter allows you to implement jQueryUI tabs within your help page, using a simple shortcode/token format. The styling for the jQueryTabs widget matches that of the standard processwire admin theme tabs, so that users will feel familiar with the interface. Instructions: 1) Install the ProcessDocumentation module. It will also install the 2 textformatters. You don't need to apply those textformatters to any field, they are just used internally by the module and called in the correct order to make them work. 2) Select the field to use for the content display (e.g. body). 3) Create your content. If you want to use tabs, this is the syntax: {tab=My First Tab} Some content {tab=My 2nd Tab} Some more content {/tabs} Make sure to close the tabs or the page will break... you need 2 or more tabs for it to work. You can only currently have 1 set of tabs per page. You should be able to safely use lists and tables. 4) Create the process page under the admin. Select ProcessDocumentation as the process and then select the page to show from the tree. 5) Now you should have the menu item in your menu if you are using Reno it will be on the left, and under a parent if you setup a parent in the tree. Clicking on that will render the help page. This example uses 7 tabs. If you are superuser, you will see the edit process settings. Other users will see the edit content only, which allows them to edit the content of the help doc, make corrections or additions. If you need to prevent access to any documentation pages by any role, you just add the name of the process page to the permissions and then don't check it for that role. The module has a defined permissionMethod that checks to see if that permission is defined, and then if the user has it. Not defining individual help page permissions means they are visible to anyone with the documentation permission. There is more work to be done on CSS, and other small details.
    8 points
  2. Like a few others in this forum I have to use a shared server on GoDaddy to host a client's website. It took me about three hours to track down the problem that threw a 500 error after I installed PW 3.0.78. It was a clearly a database connection problem. I checked and rechecked my credentials; they were good. I tried everything Ryan suggested in the .htaccess file. Nothing worked. Finally I went back to the GoDaddy control panel, to Hosting Details > Manage Databases and clicked on the name of the database to bring up the Database Details screen. At the bottom it shows Hostname. This is not what I named the database, but it's what goes into the site/config file to allow the connection. It's a very long string. I hope this helps other people to connect if they have to use GoDaddy.
    5 points
  3. The last ipsum you'll ever need: http://meettheipsums.com/
    5 points
  4. FYI, sometimes it is simpler to do an in-memory search of the WireArray. E.g. $oneItem = $myWireArray->get("id=20");// id is a property in the WireArray if($oneItem) echo 'we got the item folks!'; $multipleItems = $myWireArray->find("price>500");// price is a property in the WireArray if($multipleItems->count()) echo 'We got several items';
    4 points
  5. Hi @bobbit6k Welcome to the forums . MySQL INT (unsigned) can store up to 4.2 billion. I think ProcessWire uses signed INT for integer fields, so, you get about 2.1 billion. If you need something bigger, there is MySQL BIGINT. If you need to manipulate the data as numbers, one solution is to create your own custom Fieldtype that extends FieldtypeInteger and uses BIGINT in its database schema. We can show you how if you wish...Otherwise, if you just need a "number", you can go with a text field. FYI https://dev.mysql.com/doc/refman/5.7/en/integer-types.html https://planet.mysql.com/entry/?id=13825
    3 points
  6. You need to get regular PHP arrays (from any WireArray descending object, i.e. all PW collections) using $arr->getArray() if (in_array("1", $user->trader_type->getArray())) { echo "found!"; } https://processwire.com/api/ref/wire-array/get-array/
    3 points
  7. I don't know how the mailer services are get integrated into this new and very welcomed module, @abdus. One thing I would like to see is a modulare architecture, especially for the mailer services. They should be available as wiremail-modules, and the newsletter creator should relay on these modules, already implemented into pw. I also second @flydevto integrate @justb3a s module. We should try to make our modules modulare, that we are able to focus on our main cases and don't have to be redundant.
    3 points
  8. Here is an alternative of editing the .htaccess file. You could use Jumplinks from @Mike Rockett and manage all of your 404 hits easily (as well all others redirects needed). OT: about the wp-login itself, you could create a page and a template for this, reproduce the WP login form and play a bit with the "hackers" by giving them a nice memes on login submission (last example: https://rockett.pw/jumplinks/examples)
    3 points
  9. And done. Just need to add core modules to the shared modules list that the app uses to populate drop downs. Here's a gif: https://storage.rockett.pw/~pw/modgen-gif1.gif (Edited: Inline gifs are cool, unless you can't start/stop them like in Twitter ?)
    3 points
  10. Thanks for PR. Bumped to v1.6.7: - Control for line endings - Extend directory start list with a scan of the templates subfolder - Change icon to pencil-square-o - CodeMirror update to 5.30.0
    3 points
  11. Yes, add fields for all the settings you need (e.g. with @Soma's ColorPicker module). Then add the styles inside style.php like you quoted above. body { background:<?=$page->bgcolor-field ?> url(<?=$page->bgimage-field ?>) no-repeat; } /* ...any other styles, with or without PHP code */ Then, in your regular template file, include the CSS settings page. <link rel="stylesheet" href="<?= $pages->get('/your/css/page/')->url ?>"> Basically, you've now created a separate PHP file for all the CSS so you don't have parts in a regular stylesheet and others in your template file. Once everything works, you can go into the style template's settings and switch on caching. Enter a cache time (like 86400 to regenerate the CSS only once a day) and you have performance close to a flat file stylesheet.
    3 points
  12. A client of mine was asking for a solution to send newsletter mails to a list of subscribers. I looked around for a module, but couldn't find any. Then I saw a screenshot on this blog post about UIKit update, and decided to recreate it. Huge thanks to @ryan for the inspiration. The module uses regular pages for building HTML content. These pages can be used to create a fallback link in emails (i.e. "Use this link if you can't view email properly"). During render it injects $page->mailerMode, which can be used to change page output between text and HTML, or to show a simplified, email only HTML output. Screenshots: Main screen is just a list of items. Create page: Module configuration page: During installation, module creates a page under admin for storing items similar to FieldtypeRepeater. It also creates some fields for storing mail info Todo: More testing Sending in batches (with a script that runs in background and real-time progress log) Plans: Integration with Mailchimp (for subscriber lists) Automation (as a separate module for creating email content pages) I'm hoping to complete and release the module in the following days. I think these features should be enough for the beginning, but I'm open to suggestions.
    2 points
  13. For all of you who do not want to install a module: I have written a code snippet which could be copied into the ready.php. But first of all you have to include the Simple HTML dom parser to your project - I recommend to install it via composer. This is important because the manipulation of the markup depends on this library. I use the manipulations only on my "body" field, so therefore I wrote if($page->template->hasField('body')){ but you can change the name of the field according to your needs. So here we go: Copy this code into your ready.php /** * UIkit Textformatter for body field * * Changes various HTML elements to UIKit markup elements in the body field * * Tables * Unordered lists * Unordered list items * Ordered lists * Tooltips on links * Blockquotes */ if($page->template->hasField('body')){ $bodydom = HtmlDomParser::str_get_html($page->body); if (!empty($bodydom)) { //tables $tables = $bodydom->find('table'); foreach($tables as $table){ $table->style = null; $table->cellspacing = null; $table->cellpadding = null; $table->border = null; if($table->class){ $table->class = 'uk-table '.$table->class; } else { $table->class = 'uk-table'; } } //unordered lists $ulists = $bodydom->find('ul'); foreach($ulists as $list){ if($list->class){ $list->class = 'contentlist uk-list uk-list-space '.$list->class; } else { $list->class = 'contentlist uk-list uk-list-space'; } } //unordered list items foreach($bodydom->find('ul li') as $li){ $li->innertext = $li->innertext; } //ordered lists $olists = $bodydom->find('ol'); foreach($olists as $list){ if($list->class){ $list->class = 'custom-counter '.$list->class; } else { $list->class = 'custom-counter'; } } //textlinks $anchors = $bodydom->find('a'); foreach($anchors as $a){ if(!empty(strip_tags($a->innertext))){ $a->class = "textlink"; $a->{'data-uk-tooltip'} = ''; } } //blockquotes $blockquotes = $bodydom->find('blockquote'); foreach($blockquotes as $b){ $b->innertext = '<i class="fa fa-quote-left fa-2x uk-align-left"></i>'.$b->innertext; } //Manipulating figcaption with uikit css class foreach (($bodydom->find('figcaption')) as $caption) { $caption->class = 'uk-thumbnail-caption'; //add class to figure caption tag } foreach (($bodydom->find('img')) as $img) { //manipulate image links with tooltip and lightbox attributes if ($img->parent->tag == 'a') { $pageId = (int) wire($this->page)->get('id'); //get current page id for lightbox group $img->parent->{'data-uk-tooltip'} = ''; //add tooltip attribute $img->parent->{'data-uk-lightbox'} = '{group:\'' . $pageId . '\'}'; //add lightbox attribute if ($img->alt) { $img->parent->title = $img->alt; //add alt attribute as anchor title } else { $img->parent->title = __("Lightbox view of the image"); //add default anchor title } } //create case types if (($img->parent->tag != 'a') && ($img->parent->tag != 'figure')) { $case = 'img'; } if (($img->parent->tag == 'a') && ($img->parent->parent->tag != 'figure')) { $case = "a img"; } if ($img->parent->tag == 'figure') { $case = "figure img"; } if (($img->parent->tag == 'a') && ($img->parent->parent->tag == 'figure')) { $case = "figure a img"; } switch ($case) { case 'img': //create space before image class if ($img->class) { $img->class = ' ' . $img->class; } $img->class = 'uk-thumbnail' . $img->class; if (strpos($img->class, 'align_left') !== false) { $img->class = str_replace('align_left', 'uk-align-left', $img->class); } elseif (strpos($img->class, 'align_right') !== false) { $img->class = str_replace('align_right', 'uk-align-right', $img->class); } elseif (strpos($img->class, 'align_center') !== false) { $img->class = str_replace('align_center', 'uk-align-center uk-text-center', $img->class); } else { $img->class = $img->class . ' no-align'; $img->outertext = '<span class="uk-display-block uk-margin-bottom">' . $img->outertext . '</span>'; } break; case 'a img': $img->parent->class = 'uk-thumbnail ' . $img->class; if (strpos($img->class, 'align_left') !== false) { $img->parent->class = str_replace('align_left', 'uk-align-left', $img->parent->class); $img->outertext = '<span class="uk-overlay uk-overlay-hover">' . $img->outertext . '<span class="uk-overlay-panel uk-overlay-background uk-overlay-icon"></span></span>'; } elseif (strpos($img->class, 'align_right') !== false) { $img->parent->class = str_replace('align_right', 'uk-align-right', $img->parent->class); $img->outertext = '<span class="uk-overlay uk-overlay-hover">' . $img->outertext . '<span class="uk-overlay-panel uk-overlay-background uk-overlay-icon"></span></span>'; } elseif (strpos($img->class, 'align_center') !== false) { $img->parent->class = str_replace('align_center', 'uk-align-center uk-display-inline-block', $img->parent->class); $img->outertext = '<span class="uk-overlay uk-overlay-hover">' . $img->outertext . '<span class="uk-overlay-panel uk-overlay-background uk-overlay-icon"></span></span>'; $img->parent->outertext = '<span class="uk-display-block uk-text-center test">' . $img->parent->outertext . '</span>'; } else { $img->parent->class = $img->class . ' no-align uk-thumbnail'; $img->outertext = '<span class="uk-overlay uk-overlay-hover">' . $img->outertext . '<span class="uk-overlay-panel uk-overlay-background uk-overlay-icon"></span></span>'; $img->parent->outertext = '<span class="uk-display-block uk-margin-bottom">' . $img->parent->outertext . '</span>'; } $img->class = null; break; case 'figure img': if (strpos($img->parent->class, 'align_left') !== false) { $img->parent->class = str_replace('align_left', 'uk-align-left', $img->parent->class); } elseif (strpos($img->parent->class, 'align_right') !== false) { $img->parent->class = str_replace('align_right', 'uk-align-right', $img->parent->class); } elseif (strpos($img->parent->class, 'align_center') !== false) { $img->parent->class = str_replace('align_center', 'uk-align-center uk-text-center', $img->parent->class); } else { $img->parent->class = 'uk-display-inline-block no-align'; } $img->class = 'uk-thumbnail'; break; case 'figure a img': if (strpos($img->parent->parent->class, 'align_left') !== false) { $img->parent->parent->class = str_replace('align_left', 'uk-align-left', $img->parent->parent->class); $img->outertext = '<div class="uk-overlay uk-overlay-hover">' . $img->outertext . '<div class="uk-overlay-panel uk-overlay-background uk-overlay-icon"></div></div>'; } elseif (strpos($img->parent->parent->class, 'align_right') !== false) { $img->parent->parent->class = str_replace('align_right', 'uk-align-right', $img->parent->parent->class); $img->outertext = '<div class="uk-overlay uk-overlay-hover">' . $img->outertext . '<div class="uk-overlay-panel uk-overlay-background uk-overlay-icon"></div></div>'; } elseif (strpos($img->parent->parent->class, 'align_center') !== false) { $img->parent->parent->class = str_replace('align_center', 'uk-align-center uk-text-center', $img->parent->parent->class); $img->outertext = '<div class="uk-overlay uk-overlay-hover">' . $img->outertext . '<div class="uk-overlay-panel uk-overlay-background uk-overlay-icon"></div></div>'; } else { $img->parent->parent->class = $img->parent->parent->class . ' no-align uk-display-inline-block'; $img->outertext = '<div class="uk-overlay uk-overlay-hover">' . $img->outertext . '<div class="uk-overlay-panel uk-overlay-background uk-overlay-icon"></div></div>'; } $img->parent->class = 'uk-thumbnail'; $img->class = null; break; } } //add manipulations to body field $page->body = $bodydom; } } Thats all! All these elements will be enriched with UIKit 2 Markup. Remember: If Simple HTML Dom Parser is not correctly installed, you will get an error. Some of the styles I use are the ones that I prefer. Maybe you prefer an other style that UIKit offers. So you can change the CSS classes to your prefered style. This code only should give you an inspiration on how to manipulate markup. Best regards.
    2 points
  14. Storing it as text is fine if you're not performing numeric operations on DB, But you can copy /wire/modules/Fieldtype/FieldtypeInteger.module to /site/modules and open up the file, find and change getDatabaseSchema() from public function getDatabaseSchema(Field $field) { $schema = parent::getDatabaseSchema($field); $schema['data'] = 'int NOT NULL'; return $schema; } to public function getDatabaseSchema(Field $field) { $schema = parent::getDatabaseSchema($field); $schema['data'] = 'BIGINT NOT NULL'; return $schema; } Once you refresh module list from Modules > Refresh, it'll ask you which version to use, pick the one under /site/modules Then create a new integer field, it will be set up as BIGINT in DB.
    2 points
  15. I'm working on something like this. Here's how I did it so far. Templates x 4: /tutorials/ (blog-index) /tutorials/tutorial-title/ (blog-entry) /tags/ (tag-index) /tags/tag-name/ (tag-entry) Tree structure: blog-entry has a multiple page ref field called 'tags'... ...like so: tag-entry has a multiple page ref field called 'blogPosts'... ...like so: Using: https://modules.processwire.com/modules/connect-page-fields/ (this module has been very very useful so far, written by @Robin S and recommended to me by @abdus) The fields are connected thus: So when I create a tutorial (blog-entry template), I can select a bunch of tags (or create new ones): ...the page created with 'blog-entry' is automatically added to the associated tags in the 'blogPosts' page ref field: So now you have the posts listed under the actual tag, it's as simple as just iterating over the 'blogPosts' page ref field: <?php namespace ProcessWire; ?> <div class="container py-5"> <div class="row"> <?php $tags = $pages->get("/tags/")->children; foreach ($tags as $tag): if (count($tag->blogPosts)): ?> <div class="col-md-4 mb-5 px-md-5"> <h2 class="display-4"><a href="<?= $tag->url; ?>"><?= $tag->title; ?></a></h2> <?php // return PageArray of all items in blogPosts ref field $posts = $tag->blogPosts; // sort the PageArray $posts->sort("-postDate"); // only want first 3 items $posts = $posts->slice(0, 3); // loop through the 3 items foreach ($posts as $entry): ?> <p><a href="<?= $entry->url; ?>"><?= $entry->title; ?></a></p> <?php endforeach; ?> </div> <?php endif; endforeach; ?> </div> </div> Still not decided how to list them when there are multiple tags, but hope this gives you some ideas.
    2 points
  16. Thank you! I'd also like to throw in a request for the module to optionally make backups of files before overwriting. A simple copy to .<filename>.<definable extension> would be great. Best wishes, Steve
    2 points
  17. Why not store them under admin? It will be out of your sight and users without superuser permission will not be able to see the pages under admin. Thats how PW stores repeater items, too.
    2 points
  18. A simpler way could be passing a second parameter to $pages->count() method like this $count = $pages->count('id>0', ['getTotalType' => 'calc']); // default, slower, fetches everything then counts $count = $pages->count('id>0', ['getTotalType' => 'count']); // uses SQL query, faster From the core: Results:
    2 points
  19. ah, thanks, you are right ok, so now i get 15seconds. if you really need the count-labels it seems you would need to implement some caching...
    2 points
  20. Once PW fetches pages from DB, it saves them to memory, meaning subsequent find() operations with the same selector don't really have an effect, so it's essentially one DB operation. // PagesLoaderCache.php * Cache the given selector string and options with the given PageArray * * @param string $selector * @param array $options * @param PageArray $pages * @return bool True if pages were cached, false if not * */ public function selectorCache($selector, array $options, PageArray $pages) { // get the string that will be used for caching $selector = $this->getSelectorCache($selector, $options, true); // optimization: don't cache single pages that have an unpublished status or higher if(count($pages) && !empty($options['findOne']) && $pages->first()->status >= Page::statusUnpublished) return false; $this->pageSelectorCache[$selector] = clone $pages; return true; }
    2 points
  21. How could I missed it? Will have a look at your module, @DaveP, and come back here, if there is something that I miss. @szabesz, with my logic, there will be nothing injected into your output, unless you have explicitly inserted a placeholder into your text-inputfield. But if you have inserted a placeholder plus other content, then only the other content will be displayed. The placeholder gets stripped out without $config->debug enabled. (Also should be a configurable setting)
    2 points
  22. @netcarver has already forked my module and when I figure out how, I will pull (some of) his changes into mine. Anyone else is welcome to fork and create pull requests. For example, @horst's suggestions could be quite easily incorporated - it could also be made configurable so that different dummy text source files could be selectable, but that would be stretching my skills somewhat, so I would welcome others' input.
    2 points
  23. Maybe it would be a good idea to build something like a textformatter module, that serves the desired content via placeholders (like Hanna), but more simple. For example: {{loremipsum::w=200,p=5,s=en-nonsense}} inserts 200 words in 5 paragraphs from a textbase called "en-nonsense". This way we would be able to collect and share textbases. Optionally I would like to behave the textformatter to only insert content in $config->debug mode. Without $config->debug, it silently should extract the placeholders without injecting content. Should we start on this? edit: additionally there should be an API method to retrieve content from within template files.
    2 points
  24. i think you need to do some more debugging! i just played around with a local test-setup and got this results with 10.000 pages: creation of pages: //foreach($pages->find('parent=8181') as $p) $pages->delete($p); $i=0; $tmp = range('A', 'Z'); while($i<10000) { $p = new Page(); $p->template = 'filtertest'; $p->parent = 8181; $p->title = "test$i"; $p->a = $tmp[array_rand($tmp)]; $p->b = $tmp[array_rand($tmp)]; $p->c = $tmp[array_rand($tmp)]; $p->save(); $i++; } dump (results): d($pages->find('template=filtertest, a=a, b=b')->each('title')); array (13) 14.48ms, 0.09 MB d($pages->find('template=filtertest, a|b|c=a|b|c')->each('title')); array (3084) 1110.54ms, 6.54 MB d($pages->find('template=filtertest, a|b|c%=a|b|c')->each('title')); array (3084) 1339.68ms, 6.54 MB your filter function looks totally weird to me. you have ID values as filter but then you use the slow %= selector. why? see my first example using " = " as selector should give you an instant result! also i don't understand why you are using the OR operator ( | ) for searching different fields. is the information spread over multiple fields?? shouldn't every filter-value be stored in a separate field? PS: my template "filtertest" has fields A, B and C holding letters from A-Z PPS: are you sure the selector is slowing the site down? maybe it is the way you count your number of results in the filter sidebar?
    2 points
  25. I personally have the following module running to handle users to subscribe and unsubscribe to a newsletter. If your module could take into account @justb3a's module, it would be awesome. It already render the subscription form and create the proper user with the right role on submission.
    2 points
  26. Try this: https://modules.processwire.com/modules/admin-page-field-edit-links/
    2 points
  27. I'm confused by this - didn't you say that the maximum number of products you are currently listing is 37? 245 pages is more pages than you want to be loading without a limit. If you are later filtering these 245 pages down to 37 or whatever you should try and rework it so you are getting only the 37 in the initial $pages->find().
    2 points
  28. The solution from @abdus works well - you just need to change... $img = $page->randomImages[$page->randomIndex]; ...to... $img = $page->randomImages->eq($page->randomIndex); ...because Pageimages are indexed by basename not integer. This must be the result of some efficiency optimising in Hanna Code. To get around this, just add some attribute to each tag - you don't need to use this attribute anywhere in your tag code. So lets say the attribute is called "seed" (just so it looks kinda legit to the user - this attribute is not actually used to seed anything): [[random_image seed="546458"]] ...some content... [[random_image seed="afdasfd"]] So this attribute's value can be anything so long as it's not the same as another tag on the same page.
    2 points
  29. Yes, please. Some of my modules extend ProcessPageLister, for instance.
    2 points
  30. Hmm. looking at your selector, you seem to be using `blog-entries` template for category pages. The exact solution will depend on how you configured your tagging system, but assuming you've used a Page Reference field called `category` limited to categories with `blog-entries` template, then you can use: // inside category template file // $page will point to a page with category template $categorized = $pages->find("template=blog-post, category=$page"); // ^ this will give you all pages with template blog-post whose category field include current page, (current category) // i.e. all posts under current category foreach($categorized as $post) { echo $post->title . '<br>'; } There's a tutorial by @kongondo which covers multiple scenarios and strategies for categorization, it's a must read for beginners.
    2 points
  31. If it's one page meant to be used site-wide, you might consider creating a template file (let's say styles.php) for it that outputs the css (in the Files tab, set content-type to text/css and tick the box to not append the standard file). Then you can link to that page just like you do with every other stylesheet, and you can even use template cache. That way, your regular templates are kept tidy and you don't send unnecessary styles over the wire with each request. To be able to select the text/css content type, you need to add the following to your site/config.php first: $config->contentTypes = array( 'html' => 'text/html', 'txt' => 'text/plain', 'json' => 'application/json', 'xml' => 'application/xml', 'css' => 'text/css' );
    2 points
  32. Here's a screenie of the front end:
    2 points
  33. Not tested, but you can store any information inside $page (or any class that extends WireData), and do something like this: <?php // Hanna Code template if (!$page->randomImages) { $page->randomImages = $page->images->findTag('inline-body')->shuffle(); $page->randomIndex = $page->randomImages->count; } if (--$page->randomIndex >= 0) { // as per @Robin S's suggestion: // $img = $page->randomImages[$page->randomIndex]; $img = $page->randomImages->eq($page->randomIndex); echo "<img src='$img->url'/>"; } Keep in mind, this will stop showing images after all images have been used.
    2 points
  34. User agent blocking may help. From Perishable Press: <IfModule mod_rewrite.c> RewriteEngine on RewriteCond %{HTTP_USER_AGENT} ^$|\<|\>|\'|\%|\_iRc|\_Works|\@\$x|\<\?|\$x0e|\+select\+|\+union\+|1\,\1\,1\,|2icommerce|3GSE|4all|59\.64\.153\.|88\.0\.106\.|98|85\.17\.|A\_Browser|ABAC|Abont|abot|Accept|Access|Accoo|AceFTP|Acme|ActiveTouristBot|Address|Adopt|adress|adressendeutschland|ADSARobot|agent|ah\-ha|Ahead|AESOP\_com\_SpiderMan|aipbot|Alarm|Albert|Alek|Alexibot|Alligator|AllSubmitter|alma|almaden|ALot|Alpha|aktuelles|Akregat|Amfi|amzn\_assoc|Anal|Anarchie|andit|Anon|AnotherBot|Ansearch|AnswerBus|antivirx|Apexoo|appie|Aqua_Products|Arachmo|archive|arian|ASPSe|ASSORT|aster|Atari|ATHENS|AtHome|Atlocal|Atomic_Email_Hunter|Atomz|Atrop|^attach|attrib|autoemailspider|autohttp|axod|batch|b2w|Back|BackDoorBot|BackStreet|BackWeb|Badass|Baid|Bali|Bandit|Baidu|Barry|BasicHTTP|BatchFTP|bdfetch|beat|Become|Beij|BenchMark|berts|bew|big.brother|Bigfoot|Bilgi|Bison|Bitacle|Biz360|Black|Black.Hole|BlackWidow|bladder.fusion|Blaiz|Blog.Checker|Blogl|BlogPeople|Blogshares.Spiders|Bloodhound|Blow|bmclient|Board|BOI|boitho|Bond|Bookmark.search.tool|boris|Bost|Boston.Project|BotRightHere|Bot.mailto:craftbot@yahoo.com|BotALot|botpaidtoclick|botw|brandwatch|BravoBrian|Brok|Bropwers|Broth|browseabit|BrowseX|Browsezilla|Bruin|bsalsa|Buddy|Build|Built|Bulls|bumblebee|Bunny|Busca|Busi|Buy|bwh3|c\-spider|CafeK|Cafi|camel|Cand|captu|Catch|cd34|Ceg|CFNetwork|cgichk|Cha0s|Chang|chaos|Char|char\(32\,35\)|charlotte|CheeseBot|Chek|CherryPicker|chill|ChinaClaw|CICC|Cisco|Cita|Clam|Claw|Click.Bot|clipping|clshttp|Clush|COAST|ColdFusion|Coll|Comb|commentreader|Compan|contact|Control|contype|Conc|Conv|Copernic|Copi|Copy|Coral|Corn|core-project|cosmos|costa|cr4nk|crank|craft|Crap|Crawler0|Crazy|Cres|cs\-CZ|cuill|Curl|Custo|Cute|CSHttp|Cyber|cyberalert|^DA$|daoBot|DARK|Data|Daten|Daum|dcbot|dcs|Deep|DepS|Detect|Deweb|Diam|Digger|Digimarc|digout4uagent|DIIbot|Dillo|Ding|DISC|discobot|Disp|Ditto|DLC|DnloadMage|DotBot|Doubanbot|Download|Download.Demon|Download.Devil|Download.Wonder|Downloader|drag|DreamPassport|Drec|Drip|dsdl|dsok|DSurf|DTAAgent|DTS|Dual|dumb|DynaWeb|e\-collector|eag|earn|EARTHCOM|EasyDL|ebin|EBM-APPLE|EBrowse|eCatch|echo|ecollector|Edco|edgeio|efp\@gmx\.net|EirGrabber|email|Email.Extractor|EmailCollector|EmailSearch|EmailSiphon|EmailWolf|Emer|empas|Enfi|Enhan|Enterprise\_Search|envolk|erck|EroCr|ESurf|Eval|Evil|Evere|EWH|Exabot|Exact|EXPLOITER|Expre|Extra|ExtractorPro|EyeN|FairAd|Fake|FANG|FAST|fastlwspider|FavOrg|Favorites.Sweeper|Faxo|FDM\_1|FDSE|fetch|FEZhead|Filan|FileHound|find|Firebat|Firefox.2\.0|Firs|Flam|Flash|FlickBot|Flip|fluffy|flunky|focus|Foob|Fooky|Forex|Forum|ForV|Fost|Foto|Foun|Franklin.Locator|freefind|FreshDownload|FrontPage|FSurf|Fuck|Fuer|futile|Fyber|Gais|GalaxyBot|Galbot|Gamespy\_Arcade|GbPl|Gener|geni|Geona|Get|gigabaz|Gira|Ginxbot|gluc|glx.?v|gnome|Go.Zilla|Goldfire|Google.Wireless.Transcoder|Googlebot\-Image|Got\-It|GOFORIT|gonzo|GornKer|GoSearch|^gotit$|gozilla|grab|Grabber|GrabNet|Grub|Grup|Graf|Green.Research|grub|grub\-client|gsa\-cra|GSearch|GT\:\:WWW|GuideBot|guruji|gvfs|Gyps|hack|haha|hailo|Harv|Hatena|Hax|Head|Helm|herit|hgre|hhjhj\@yahoo|Hippo|hloader|HMView|holm|holy|HomePageSearch|HooWWWer|HouxouCrawler|HMSE|HPPrint|htdig|HTTPConnect|httpdown|http.generic|HTTPGet|httplib|HTTPRetriever|HTTrack|human|Huron|hverify|Hybrid|Hyper|ia\_archiver|iaskspi|IBM\_Planetwide|iCCra|ichiro|ID\-Search|IDA|IDBot|IEAuto|IEMPT|iexplore\.exe|iGetter|Ilse|Iltrov|Image|Image.Stripper|Image.Sucker|imagefetch|iimds\_monitor|Incutio|IncyWincy|Indexer|Industry.Program|Indy|InetURL|informant|InfoNav|InfoTekies|Ingelin|Innerpr|Inspect|InstallShield.DigitalWizard|Insuran\.|Intellig|Intelliseek|InterGET|Internet.Ninja|Internet.x|Internet\_Explorer|InternetLinkagent|InternetSeer.com|Intraf|IP2|Ipsel|Iria|IRLbot|Iron33|Irvine|ISC\_Sys|iSilo|ISRCCrawler|ISSpi|IUPUI.Research.Bot|Jady|Jaka|Jam|^Java|java\/|Java\(tm\)|JBH.agent|Jenny|JetB|JetC|jeteye|jiro|JoBo|JOC|jupit|Just|Jyx|Kapere|kash|Kazo|KBee|Kenjin|Kernel|Keywo|KFSW|KKma|Know|kosmix|KRAE|KRetrieve|Krug|ksibot|ksoap|Kum|KWebGet|Lachesis|lanshan|Lapo|larbin|leacher|leech|LeechFTP|LeechGet|leipzig\.de|Lets|Lexi|lftp|Libby|libcrawl|libcurl|libfetch|libghttp|libWeb|libwhisker|libwww|libwww\-FM|libwww\-perl|LightningDownload|likse|Linc|Link|Link.Sleuth|LinkextractorPro|Linkie|LINKS.ARoMATIZED|LinkScan|linktiger|LinkWalker|Lint|List|lmcrawler|LMQ|LNSpiderguy|loader|LocalcomBot|Locu|London|lone|looksmart|loop|Lork|LTH\_|lwp\-request|LWP|lwp-request|lwp-trivial|Mac.Finder|Macintosh\;.I\;.PPC|Mac\_F|magi|Mag\-Net|Magnet|Magp|Mail.Sweeper|main|majest|Mam|Mana|MarcoPolo|mark.blonin|MarkWatch|MaSagool|Mass|Mass.Downloader|Mata|mavi|McBot|Mecha|MCspider|mediapartners|^Memo|MEGAUPLOAD|MetaProducts.Download.Express|Metaspin|Mete|Microsoft.Data.Access|Microsoft.URL|Microsoft\_Internet\_Explorer|MIDo|MIIx|miner|Mira|MIRE|Mirror|Miss|Missauga|Missigua.Locator|Missouri.College.Browse|Mist|Mizz|MJ12|mkdb|mlbot|MLM|MMMoCrawl|MnoG|moge|Moje|Monster|Monza.Browser|Mooz|Moreoverbot|MOT\-MPx220|mothra\/netscan|mouse|MovableType|Mozdex|Mozi\!|^Mozilla$|Mozilla\/1\.22|Mozilla\/22|^Mozilla\/3\.0.\(compatible|Mozilla\/3\.Mozilla\/2\.01|Mozilla\/4\.0\(compatible|Mozilla\/4\.08|Mozilla\/4\.61.\(Macintosh|Mozilla\/5\.0|Mozilla\/7\.0|Mozilla\/8|Mozilla\/9|Mozilla\:|Mozilla\/Firefox|^Mozilla.*Indy|^Mozilla.*NEWT|^Mozilla*MSIECrawler|Mp3Bot|MPF|MRA|MS.FrontPage|MS.?Search|MSFrontPage|MSIE\_6\.0|MSIE6|MSIECrawler|msnbot\-media|msnbot\-Products|MSNPTC|MSProxy|MSRBOT|multithreaddb|musc|MVAC|MWM|My\_age|MyApp|MyDog|MyEng|MyFamilyBot|MyGetRight|MyIE2|mysearch|myurl|NAG|NAMEPROTECT|NASA.Search|nationaldirectory|Naver|Navr|Near|NetAnts|netattache|Netcach|NetCarta|Netcraft|NetCrawl|NetMech|netprospector|NetResearchServer|NetSp|Net.Vampire|netX|NetZ|Neut|newLISP|NewsGatorInbox|NEWT|NEWT.ActiveX|Next|^NG|NICE|nikto|Nimb|Ninja|Ninte|NIPGCrawler|Noga|nogo|Noko|Nomad|Norb|noxtrumbot|NPbot|NuSe|Nutch|Nutex|NWSp|Obje|Ocel|Octo|ODI3|oegp|Offline|Offline.Explorer|Offline.Navigator|OK.Mozilla|omg|Omni|Onfo|onyx|OpaL|OpenBot|Openf|OpenTextSiteCrawler|OpenU|Orac|OrangeBot|Orbit|Oreg|osis|Outf|Owl|P3P|PackRat|PageGrabber|PagmIEDownload|pansci|Papa|Pars|Patw|pavu|Pb2Pb|pcBrow|PEAR|PEER|PECL|pepe|Perl|PerMan|PersonaPilot|Persuader|petit|PHP|PHP.vers|PHPot|Phras|PicaLo|Piff|Pige|pigs|^Ping|Pingd|PingALink|Pipe|Plag|Plant|playstarmusic|Pluck|Pockey|POE\-Com|Poirot|Pomp|Port.Huron|Post|powerset|Preload|press|Privoxy|Probe|Program.Shareware|Progressive.Download|ProPowerBot|prospector|Provider.Protocol.Discover|ProWebWalker|Prowl|Proxy|Prozilla|psbot|PSurf|psycheclone|^puf$|Pulse|Pump|PushSite|PussyCat|PuxaRapido|PycURL|Pyth|PyQ|QuepasaCreep|Query|Quest|QRVA|Qweer|radian|Radiation|Rambler|RAMP|RealDownload|Reap|Recorder|RedCarpet|RedKernel|ReGet|relevantnoise|replacer|Repo|requ|Rese|Retrieve|Rip|Rix|RMA|Roboz|Rogue|Rover|RPT\-HTTP|Rsync|RTG30|.ru\)|ruby|Rufus|Salt|Sample|SAPO|Sauger|savvy|SBIder|SBP|SCAgent|scan|SCEJ\_|Sched|Schizo|Schlong|Schmo|Scout|Scooter|Scorp|ScoutOut|SCrawl|screen|script|SearchExpress|searchhippo|Searchme|searchpreview|searchterms|Second.Street.Research|Security.Kol|Seekbot|Seeker|Sega|Sensis|Sept|Serious|Sezn|Shai|Share|Sharp|Shaz|shell|shelo|Sherl|Shim|Shiretoko|ShopWiki|SickleBot|Simple|Siph|sitecheck|SiteCrawler|SiteSnagger|Site.Sniper|SiteSucker|sitevigil|SiteX|Sleip|Slide|Slurpy.Verifier|Sly|Smag|SmartDownload|Smurf|sna\-|snag|Snake|Snapbot|Snip|Snoop|So\-net|SocSci|sogou|Sohu|solr|sootle|Soso|SpaceBison|Spad|Span|spanner|Speed|Spegla|Sphere|Sphider|spider|SpiderBot|SpiderEngine|SpiderView|Spin|sproose|Spurl|Spyder|Squi|SQ.Webscanner|sqwid|Sqworm|SSM\_Ag|Stack|Stamina|stamp|Stanford|Statbot|State|Steel|Strateg|Stress|Strip|studybot|Style|subot|Suck|Sume|sun4m|Sunrise|SuperBot|SuperBro|Supervi|Surf4Me|SuperHTTP|Surfbot|SurfWalker|Susi|suza|suzu|Sweep|sygol|syncrisis|Systems|Szukacz|Tagger|Tagyu|tAke|Talkro|TALWinHttpClient|tamu|Tandem|Tarantula|tarspider|tBot|TCF|Tcs\/1|TeamSoft|Tecomi|Teleport|Telesoft|Templeton|Tencent|Terrawiz|Test|TexNut|trivial|Turnitin|The.Intraformant|TheNomad|Thomas|TightTwatBot|Timely|Titan|TMCrawler|TMhtload|toCrawl|Todobr|Tongco|topic|Torrent|Track|translate|Traveler|TREEVIEW|True|Tunnel|turing|Turnitin|TutorGig|TV33\_Mercator|Twat|Tweak|Twice|Twisted.PageGetter|Tygo|ubee|UCmore|UdmSearch|UIowaCrawler|Ultraseek|UMBC|unf|UniversalFeedParser|unknown|UPG1|UtilMind|URLBase|URL.Control|URL\_Spider\_Pro|urldispatcher|URLGetFile|urllib|URLSpiderPro|URLy|User\-Agent|UserAgent|USyd|Vacuum|vagabo|Valet|Valid|Vamp|vayala|VB\_|VCI|VERI\~LI|verif|versus|via|Viewer|virtual|visibilitygap|Visual|vobsub|Void|VoilaBot|voyager|vspider|VSyn|w\:PACBHO60|w0000t|W3C|w3m|w3search|walhello|Walker|Wand|WAOL|WAPT|Watch|Wavefire|wbdbot|Weather|web.by.mail|Web.Data.Extractor|Web.Downloader|Web.Ima|Web.Mole|Web.Sucker|Web2Mal|Web2WAP|WebaltBot|WebAuto|WebBandit|Webbot|WebCapture|WebCat|webcraft\@bea|Webclip|webcollage|WebCollector|WebCopier|WebCopy|WebCor|webcrawl|WebDat|WebDav|webdevil|webdownloader|Webdup|WebEMail|WebEMailExtrac|WebEnhancer|WebFetch|WebGo|WebHook|Webinator|WebInd|webitpr|WebFilter|WebFountain|WebLea|Webmaster|WebmasterWorldForumBot|WebMin|WebMirror|webmole|webpic|WebPin|WebPix|WebReaper|WebRipper|WebRobot|WebSauger|WebSite|Website.eXtractor|Website.Quester|WebSnake|webspider|Webster|WebStripper|websucker|WebTre|WebVac|webwalk|WebWasher|WebWeasel|WebWhacker|WebZIP|Wells|WEP\_S|WEP.Search.00|WeRelateBot|wget|Whack|Whacker|whiz|WhosTalking|Widow|Win67|window.location|Windows.95\;|Windows.95\)|Windows.98\;|Windows.98\)|Winodws|Wildsoft.Surfer|WinHT|winhttp|WinHttpRequest|WinHTTrack|Winnie.Poh|wire|WISEbot|wisenutbot|wish|Wizz|WordP|Works|world|WUMPUS|Wweb|WWWC|WWWOFFLE|WWW\-Collector|WWW.Mechanize|www.ranks.nl|wwwster|^x$|X12R1|x\-Tractor|Xaldon|Xenu|XGET|xirq|Y\!OASIS|Y\!Tunnel|yacy|YaDirectBot|Yahoo\-MMAudVid|YahooSeeker|YahooYSMcm|Yamm|Yand|yang|Yeti|Yoono|yori|Yotta|YTunnel|Zade|zagre|ZBot|Zeal|ZeBot|zerx|Zeus|ZIPCode|Zixy|zmao|Zyborg [NC] RewriteRule ^(.*)$ - [F,L] </IfModule> Or block requests directly if `name` parameter includes your strings RewriteCond %{QUERY_STRING} (^|&)name=(Not%20Recognized|No%20Subscription%20Detected)(&|$) RewriteRule ^(.*) - [F] It looks like "hackers" are using a paid tool with expired/pirated/trial license
    2 points
  35. I've encountered the same problem with many people specifying that any bids for a web site must be Wordpress. I come from a database development background, mostly doing Microsoft Access desktop apps, but also some web development, and even made my own CMS way back when Wordpress was only a dream waiting to happen. I'd describe Processwire as being data driven, whereas Wordpress is content driven. By that I mean that Wordpress revolves around posts and pages, whereas although Processwire calls them Pages, Processwire pages are really totally different beasts to Wordpress pages, and are really a less nerdy name for what are really objects, which can have any properties you like, and may not even be 'pages' in the publishing sense at all. If you want a blog using an existing theme, Wordpress is the way to go. If you want a web site that has to deal with pretty much any data structures you want to throw at it, Processwire is the way to go. Wordpress needs a plugin to do custom field types, and plugins to do lots of other things, and those plugins don't necessarily peacefully coexist or have consistent UIs. With Processwire, you start off bare-bones but can build anything you like quickly and efficiently. The development process for me is far more like building something with Microsoft Access, in that you design you data structures (fields, and I believe with Profields, you can actually do tables, but I haven't had enough work to justify that yet) and then add them to templates which are like forms or reports in Access. Site profiles are a bit like predefined Access templates for specific tasks. Perhaps it would be good to work towards a wider range of free and premium site templates available, but rather than modelling them on Wordpress themes, model them on Access templates, then people will see that Processwire is more of an app platform than just a web site CMS. Processwire can't really have 'themes' in the Wordpress sense, because those rely on assumptions about what data structures you have, whereas with Processwire, a site profile has to define data structures as well as presentation, as Processwire doesn't have any inherent data structures like posts or pages in a Wordpress sense. The reason Access was, and still is so wildly popular amongst a small group of developers is that it is the quickest way to develop a desktop front end for pretty much any kind of database app you might want to build, even if it has some inherent issues that IT departments don't always like. There are a few things I wish Processwire did differently, eg I'd like referential integrity at the database level, and I'd like to be able to use other database systems other than mySQL/MariaDB, (eg PostgreSQL, SQL Server) , but the reality is it's the most efficient tool I've found for quickly defining and presenting any kind of data on the web. With Wordpress, structured data is an afterthought, with Processwire it's core.
    2 points
  36. I struggled at first to realize where to combine the user specific branch limitation with the user but as i found out it started to realize how it works and it's doing it's job. Thanks you very much!
    1 point
  37. @Livius - welcome to the forums! If it's just one branch per user, then this will do what you need: http://modules.processwire.com/modules/admin-restrict-branch/
    1 point
  38. Just needed a few days ago: $pages->find("children.children.id=1028")
    1 point
  39. Awesome job!. Seems this could become very handy when making projects for clients.
    1 point
  40. Another option might be the FieldtypeDecimal module: https://processwire.com/talk/topic/7542-development-fieldtypefloat-fieldtypedecimal/?do=findComment&comment=139097
    1 point
  41. I'm having trouble with my selectors when using !=. I'm sure I'm making some newbie mistake, but I'm just not sure how to fix it. This code below functions as expected: $results = $pages->find("template=basic-post, limit=1, path=$post1path, sort=-userpubdate"); but this one (the one I actually need) doesn't work: $results = $pages->find("template=basic-post, limit=1, path!=$post1path, sort=-userpubdate"); It results in an internal server error. How should I have phrased it instead? My intent is to find all pages with the basic-post template but excluding that one specific post. In both cases, $post1path = $post1->url; echo $post1path; where $post1path echoes as expected with the path of post1. The variables therefore seem to be working, but I must be making some sort of fundamental newbie error in my page selection. I would appreciate any guidance that anyone can give. I didn't want to use slice() or other things after getting the page array, as I want to be able to use pagination. UPDATE: I *think* I have gotten around the issue by using ID's instead, where $post1id = $post1->id. $results = $pages->find("template=basic-post, limit=1, id!=$post1id, sort=-userpubdate"); And it seems to paginate correctly as far as I can see - I still have to do more testing with a bigger array to be certain, but it's working on my small test array for now. I'm still curious why path!=$post1path did not work, if anyone would like to comment on that for me. But at least there is a solution that, so far at least, seems to work.
    1 point
  42. @fbg13 Yes absolutely, just copypasted the previous post in case he was using the image field (and btw, the if condition do not make sense, thanks). But should be $form->login_submit->value as $form->login_submit return an object.
    1 point
  43. I have also written the login/logout system on my own (I needed UIKit Markup and some other customizations). To prevent spam I use this Honeypot class and I have no problem since then. It make several tests before letting the user go further. I have installed it via composer so updating is also no problem. So its a look worth while. Best regards
    1 point
  44. Check out Video Fieldtype Keep in mind that it requires ffmpeg installed on your server, so that might not be ideal.
    1 point
  45. I think just $form->login_submit = "???"; should do it. $wire->addHookAfter('LoginRegister::buildLoginForm', function($event) { $form = $event->return; $form->description = false; $form->login_submit->value = "???"; $event->return = $form; });
    1 point
  46. One very easy and effective solution is to use honeypots. Ryan also uses this technique for Formbuilder and has (like me) very good results. Just remember to turn off the autofill option for the input to prevent the browser from filling your hidden field and marking it as spam.
    1 point
  47. Tracy will report all those errors even with debug mode off - just use the "Force superuser into development mode" option so that it shows on a live production site when you are logged in.
    1 point
  48. Not sure why you are seeing that. What you should see is an exception message that explains things pretty well: IDs are the way to go for that sort of selector, so I would stick to what you have changed to rather than install PagePaths. Edit: it just occurred to me that you may not be seeing the exception if do not have debug mode enabled. In /site/config.php: $config->debug = true; You should enable debug mode while you are developing a site and then disable debug mode when the site goes to production.
    1 point
  49. Hi, I do not think there are solid statistics to showcase but we have good blog posts you might use to pick the info you can use to persuade clients: https://processwire.com/blog/posts/building-canongate/ https://processwire.com/blog/posts/cms-critic-powered-by-processwire-again-case-study/ https://processwire.com/blog/posts/new-2.8-version-current-projects-and-pw-usage/ https://processwire.com/blog/posts/roadmap-2017/ etc... Also, you can find good case studies here: https://processwire.com/talk/forum/9-showcase/ https://processwire.com/talk/forum/16-case-studies/ https://weekly.pw/ (site of the week) Hope this helps.
    1 point
  50. It is very difficult to choose a framework, that's why I never use one . I just use SASS with normalize.css, bourbon bitter and a grid system I've built. This requires more work at first, but you avoid the bloat.
    1 point
×
×
  • Create New...